From 3143c00729a536c984c5720ee6bb7cad5aae8090 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 7 May 2024 14:50:23 +0200 Subject: [PATCH 01/45] EgtGeomKernel : - aggiunte le funzioni ProjectCurveOnSurfBez e la sua versione estesa. --- EgtGeomKernel.vcxproj | 1 + EgtGeomKernel.vcxproj.filters | 3 ++ ProjectCurveSurfBez.cpp | 55 +++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 ProjectCurveSurfBez.cpp diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 801df76..f85d609 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -319,6 +319,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index edcd982..34d8382 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -537,6 +537,9 @@ File di origine\Base + + File di origine\GeoProject + diff --git a/ProjectCurveSurfBez.cpp b/ProjectCurveSurfBez.cpp new file mode 100644 index 0000000..5d2263c --- /dev/null +++ b/ProjectCurveSurfBez.cpp @@ -0,0 +1,55 @@ +//---------------------------------------------------------------------------- +// EgalTech 2024-2024 +//---------------------------------------------------------------------------- +// File : ProjectCurveSurfBez.cpp Data : 07.05.24 Versione : 2.6e3 +// Contenuto : Implementazione funzioni proiezione curve su superficie Bezier. +// +// +// +// Modifiche : 07.05.24 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "/EgtDev/Include/EGkProjectCurveSurfTm.h" +#include "/EgtDev/Include/EGkSurfBezier.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen, + PNT5AXVECTOR& vPt5ax) +{ + const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ; + return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, vtDir, dLinTol, dMaxSegmLen, vPt5ax) ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const IGeoPoint3d& gpRef, + double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) +{ + const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ; + return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, gpRef, dLinTol, dMaxSegmLen, vPt5ax) ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const ICurve& crRef, + double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) +{ + const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ; + return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, crRef, dLinTol, dMaxSegmLen, vPt5ax) ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const ISurfTriMesh& tmRef, + double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) +{ + const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ; + return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, tmRef, dLinTol, dMaxSegmLen, vPt5ax) ; +} From d6567e94c467f9a2a418d3fa4e835eb67ac768bd Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 8 May 2024 17:49:31 +0200 Subject: [PATCH 02/45] EgtGeomKernel : - aggiunta funzione MakeRational per curve di Bezier - aggiunta funzione per la conversione in Bezier di una ICurve. --- CurveAux.cpp | 34 ++++++++++++++++++++++++++++++++++ CurveBezier.cpp | 14 ++++++++++++++ CurveBezier.h | 1 + 3 files changed, 49 insertions(+) diff --git a/CurveAux.cpp b/CurveAux.cpp index a9e861c..4f32309 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -403,6 +403,40 @@ CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) return true ; } +//---------------------------------------------------------------------------- +ICurve* +CurveToBezierCurve( const ICurve* pCrv) +{ + PtrOwner pBezierForm ; + switch ( pCrv->GetType()) { + case CRV_LINE :{ + const ICurveLine* pCrvLine = static_cast( pCrv) ; + pBezierForm.Set( LineToBezierCurve( pCrvLine)) ; + break ; + } + case CRV_ARC : { + const ICurveArc* pCrvArc = static_cast( pCrv) ; + pBezierForm.Set( ArcToBezierCurve( pCrvArc)) ; + break ; + } + case CRV_COMPO : { + const ICurveComposite* pCrvCompo = static_cast( pCrv) ; + pBezierForm.Set( CompositeToBezierCurve( pCrvCompo)) ; + break ; + } + case CRV_BEZIER : { + const ICurveBezier* pCrvBezier = static_cast( pCrv) ; + pBezierForm.Set( BezierToBasicBezierCurve( pCrvBezier)) ; + break ; + } + default : + return nullptr ; + break ; + } + + return Release( pBezierForm) ; +} + //---------------------------------------------------------------------------- ICurveBezier* LineToBezierCurve( const ICurveLine* pCrvLine) diff --git a/CurveBezier.cpp b/CurveBezier.cpp index afc6c6d..8fd2aed 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -2208,3 +2208,17 @@ CurveBezier::ResetVoronoiObject() const delete m_pVoronoiObj ; m_pVoronoiObj = nullptr ; } + +//---------------------------------------------------------------------------- +bool +CurveBezier::MakeRational( void) +{ + if ( m_bRat) + return true ; + // creo il vettore dei pesi e li setto tutti a 1 + m_vWeCtrl.assign( m_nDeg + 1, 1) ; + // aggiorno il flag rational + m_bRat = true ; + + return true ; +} diff --git a/CurveBezier.h b/CurveBezier.h index b402f6c..e51780a 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -148,6 +148,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW double GetControlWeight( int nInd, bool* pbOk = NULL) const override ; bool GetControlPolygonLength( double& dLen) const override ; int GetSingularParam( double& dPar) const override ; + bool MakeRational( void) override ; public : // IGeoObjRW int GetNgeId( void) const override ; From 5f56152a8b715464bd7fb712f983effef4b1f781 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 9 May 2024 15:13:25 +0200 Subject: [PATCH 03/45] EgtGeomKernel : - aggiunte le funzioni per creare SurfBez da estrusione e da FlatContour. --- EgtGeomKernel.vcxproj | 1 + EgtGeomKernel.vcxproj.filters | 3 + SbzFromCurves.cpp | 1145 +++++++++++++++++++++++++++++++++ SurfBezier.cpp | 296 ++++++--- SurfBezier.h | 4 + 5 files changed, 1374 insertions(+), 75 deletions(-) create mode 100644 SbzFromCurves.cpp diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index f85d609..e2b97ac 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -323,6 +323,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 34d8382..3fe049e 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -540,6 +540,9 @@ File di origine\GeoProject + + File di origine\GeoCreate + diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp new file mode 100644 index 0000000..fe871ab --- /dev/null +++ b/SbzFromCurves.cpp @@ -0,0 +1,1145 @@ +//---------------------------------------------------------------------------- +// EgalTech 20024 +//---------------------------------------------------------------------------- +// File : SbzFromCurves.cpp Data : 07.05.24 Versione : 2.6e2 +// Contenuto : Implementazione di funzioni per creazione di superfici Sbz +// a partire da curve, con diversi metodi. +// +// +// Modifiche : 07.05.24 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "GeoConst.h" +#include "CurveLine.h" +#include "CurveArc.h" +#include "CurveComposite.h" +#include "SurfTriMesh.h" +#include "SurfBezier.h" +#include "Voronoi.h" +#include "/EgtDev/Include/EGkSfrCreate.h" +#include "/EgtDev/Include/EGkOffsetCurve.h" +#include "/EgtDev/Include/EGkStmFromCurves.h" +#include "/EgtDev/Include/EGkStmFromTriangleSoup.h" +#include "/EgtDev/Include/EGkRotationMinimizingFrame.h" +#include "/EgtDev/Include/EGkRotationXplaneFrame.h" +#include "/EgtDev/Include/EGkIntersCurves.h" +#include "/EgtDev/Include/EGkSurfBezier.h" +#include "/EgtDev/Include/EGkSbzFromCurves.h" +#include "/EgtDev/Include/EgtPointerOwner.h" +#include + +using namespace std ; + +////------------------------------------------------------------------------------- +//static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, +// POLYLINEVECTOR& vPL, Vector3d& vtN) ; + +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol) +{ + // verifica parametri + if ( pCurve == nullptr) + return nullptr ; + // calcolo la polilinea che approssima la curva + PolyLine PL ; + if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + return nullptr ; + // creo e setto la superficie trimesh + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByFlatContour( PL)) + return nullptr ; + //// salvo tolleranza lineare usata + //pSTM->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} + +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione///////////////////////////////////////////////// +//{ +// // verifica parametri +// if ( &vpCurve == nullptr || vpCurve.empty()) +// return nullptr ; +// // calcolo le polilinee che approssimano le curve della regione +// POLYLINEVECTOR vPL ; +// Vector3d vtN ; +// if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN)) +// return nullptr ; +// // creo e setto la superficie trimesh +// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL)) +// return nullptr ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// // restituisco la superficie +// return Release( pSTM) ; +//} + +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, + bool bCapEnds, double dLinTol) +{ + // verifica parametri + if ( pCurve == nullptr || &vtExtr == nullptr) + return nullptr ; + // calcolo la polilinea che approssima la curva + PolyLine PL ; + if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + return nullptr ; + // se richiesta chiusura agli estremi + bool bDoCapEnds = false ; + if ( bCapEnds) { + // verifico che la curva sia chiusa e piatta + Plane3d plPlane ; + double dArea ; + if ( PL.IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) { + // componente dell'estrusione perpendicolare al piano della curva + double dOrthoExtr = plPlane.GetVersN() * vtExtr ; + if ( ( abs( dOrthoExtr) > EPS_SMALL)) { + bDoCapEnds = true ; + // se negativa, inverto il senso del contorno + if ( dOrthoExtr < 0) + PL.Invert() ; + } + } + } + + + //PtrOwner pBezierForm( CurveToBezierCurve( pCurve)) ; + PtrOwner pBezierForm( pCurve->Clone()) ; + // creo e setto la superficie trimesh + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr)) + return nullptr ; + + //// se da fare, metto i tappi sulle estremità + //if ( bDoCapEnds) { + // // creo la prima superficie di estremità + // SurfTriMesh STM1 ; + // if ( ! STM1.CreateByFlatContour( PL)) + // return nullptr ; + // // la copio + // SurfTriMesh STM2 = STM1 ; + // // inverto la prima superficie + // STM1.Invert() ; + // // traslo la seconda + // STM2.Translate( vtExtr) ; + + // ////// SurfCompo? + // //// le unisco alla superficie del fianco + // //if ( ! pSbz->DoSewing( STM1) || ! pSTM->DoSewing( STM2)) + // // return nullptr ; + //} + //// salvo tolleranza lineare usata + //pSbz->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} + +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr) +// return nullptr ; +// // se una sola curva, uso la funzione precedente +// if ( vpCurve.size() == 1 ) +// return GetSurfTriMeshByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ; +// // calcolo le polilinee che approssimano le curve della regione +// POLYLINEVECTOR vPL ; +// Vector3d vtN ; +// if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN)) +// return nullptr ; +// // verifico la direzione di estrusione +// double dOrthoExtr = vtN * vtExtr ; +// if ( ( abs( dOrthoExtr) < EPS_SMALL)) +// return nullptr ; +// // se componente estrusione negativa, inverto tutti i percorsi +// if ( dOrthoExtr < 0) { +// for ( int i = 0 ; i < int( vPL.size()) ; ++ i) +// vPL[i].Invert() ; +// } +// // creo la prima superficie di estremità +// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL)) +// return nullptr ; +// // creo la seconda superficie e la unisco alla prima +// { // copio la prima superficie +// SurfTriMesh STM2 = *pSTM ; +// // inverto la prima superficie +// pSTM->Invert() ; +// // traslo la seconda +// STM2.Translate( vtExtr) ; +// // la unisco alla prima +// if ( ! pSTM->DoSewing( STM2)) +// return nullptr ; +// } +// // creo e unisco le diverse superfici di estrusione +// for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { +// // estrusione +// SurfTriMesh STM2 ; +// if ( ! STM2.CreateByExtrusion( vPL[i], vtExtr)) +// return nullptr ; +// // la unisco alla superficie principale +// if ( ! pSTM->DoSewing( STM2)) +// return nullptr ; +// } +// // compatto la superficie +// if ( ! pSTM->DoCompacting()) +// return nullptr ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// // restituisco la superficie +// return Release( pSTM) ; +//} + +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, +// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) +// return nullptr ; +// // limite minimo su tolleranza +// dLinTol = max( dLinTol, EPS_SMALL) ; +// // calcolo la polilinea che approssima la curva +// PolyLine PL ; +// if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) +// return nullptr ; +// // calcolo lo step di rotazione +// double dMaxRad = 0 ; +// if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) +// return nullptr ; +// double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; +// // se richiesta chiusura degli estremi +// if ( bCapEnds && ! PL.IsClosed()) { +// Vector3d vtAxN = vtAx ; +// vtAxN.Normalize() ; +// double dPosIni = 0, dPosFin = 0 ; +// Point3d ptP ; +// // proietto l'ultimo punto sull'asse di rotazione +// if ( PL.GetLastPoint( ptP)) { +// dPosFin = ( ptP - ptAx) * vtAxN ; +// Point3d ptPOnAx = ptAx + dPosFin * vtAxN ; +// // se non giace sull'asse, aggiungo il punto proiettato +// if ( ! AreSamePointApprox( ptP, ptPOnAx)) { +// double dU ; +// PL.GetLastU( dU) ; +// PL.AddUPoint( ( dU + 1), ptPOnAx) ; +// } +// } +// // inverto la polilinea +// PL.Invert() ; +// // proietto l'ultimo punto (era il primo) sull'asse di rotazione +// if ( PL.GetLastPoint( ptP)) { +// dPosIni = ( ptP - ptAx) * vtAxN ; +// Point3d ptPOnAx = ptAx + dPosIni * vtAxN ; +// // se non giace sull'asse, aggiungo il punto proiettato +// if ( ! AreSamePointApprox( ptP, ptPOnAx)) { +// double dU ; +// PL.GetLastU( dU) ; +// PL.AddUPoint( ( dU + 1), ptPOnAx) ; +// } +// } +// // decido se reinvertire la polilinea +// if ( dPosFin > dPosIni) +// PL.Invert() ; +// } +// // creo e setto la superficie trimesh +// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSTM) || ! pSTM->CreateByScrewing( PL, ptAx, vtAx, ANG_FULL, dStepRotDeg, 0)) +// return nullptr ; +// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno +// double dVol ; +// if ( pSTM->GetVolume( dVol) && dVol < 0) +// pSTM->Invert() ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, +// double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) +// return nullptr ; +// // limite minimo su tolleranza +// dLinTol = max( dLinTol, EPS_SMALL) ; +// // calcolo la polilinea che approssima la curva +// PolyLine PL ; +// if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) +// return nullptr ; +// // calcolo lo step di rotazione +// double dMaxRad = 0 ; +// if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) +// return nullptr ; +// double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; +// // se superficie rototraslata, necessari limiti sulla lunghezza dei segmenti +// if ( abs( dAngRotDeg) > EPS_ANG_SMALL && abs( dMove) > EPS_SMALL){ +// double dLenMax = 2.5 * abs( dMove * dStepRotDeg / dAngRotDeg) ; +// if ( ! PL.AdjustForMaxSegmentLen( dLenMax)) +// return nullptr ; +// } +// // creo e setto la superficie trimesh +// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSTM) || ! pSTM->CreateByScrewing( PL, ptAx, vtAx, dAngRotDeg, dStepRotDeg, dMove)) +// return nullptr ; +// // se richiesti caps +// if ( bCapEnds) { +// // determino se la sezione è chiusa e piatta +// Plane3d plPlane ; double dArea ; +// bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ; +// // determino non sia una semplice rivoluzione +// bool bRevolved = ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL && abs( dMove) < EPS_SMALL) ; +// // se sezione chiusa e piatta e non rivoluzione, posso aggiungere i tappi +// if ( bSectClosedFlat && ! bRevolved) { +// // aggiungo il cap sull'inizio +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) +// return nullptr ; +// pSTM->DoSewing( *pSci) ; +// // aggiungo il cap sulla fine +// Vector3d vtMove = vtAx ; +// vtMove.Normalize() ; +// vtMove *= dMove ; +// PL.Translate( vtMove) ; +// PL.Rotate( ptAx, vtAx, dAngRotDeg) ; +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) +// return nullptr ; +// pSce->Invert() ; +// pSTM->DoSewing( *pSce) ; +// } +// } +// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno +// double dVol ; +// if ( pSTM->GetVolume( dVol) && dVol < 0) +// pSTM->Invert() ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//static ISurfBezier* +//GetSurfBezierSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifico che la linea guida sia piana +// Plane3d plGuide ; +// if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) +// return nullptr ; +// Vector3d vtNorm = plGuide.GetVersN() ; +// // determino se la guida è chiusa +// bool bGuideClosed = pGuide->IsClosed() ; +// // curve di offset +// OffsetCurve OffsCrvR ; +// if ( ! OffsCrvR.Make( pGuide, dDimH / 2, ICurve::OFF_FILLET) || OffsCrvR.GetCurveCount() == 0) +// return nullptr ; +// PtrOwner pCrvR( OffsCrvR.GetLongerCurve()) ; +// if ( IsNull( pCrvR)) +// return nullptr ; +// OffsetCurve OffsCrvL ; +// if ( ! OffsCrvL.Make( pGuide, -dDimH / 2, ICurve::OFF_FILLET) || OffsCrvL.GetCurveCount() == 0) +// return nullptr ; +// PtrOwner pCrvL( OffsCrvL.GetLongerCurve()) ; +// if ( IsNull( pCrvL)) +// return nullptr ; +// // costruisco le parti di superficie +// PtrOwner pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; +// if ( IsNull( pSrfTop)) +// return nullptr ; +// PtrOwner pSrfBot( pSrfTop->Clone()) ; +// if ( IsNull( pSrfBot)) +// return nullptr ; +// pSrfBot->Translate( -dDimV * vtNorm) ; +// pSrfBot->Invert() ; +// PtrOwner pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ; +// if ( IsNull( pSrfRgt)) +// return nullptr ; +// pSrfRgt->Invert() ; +// PtrOwner pSrfLft( GetSurfTriMeshByExtrusion( pCrvL, -dDimV * vtNorm, false, dLinTol)) ; +// if ( IsNull( pSrfLft)) +// return nullptr ; +// // unisco le parti +// PtrOwner pSTM( Release( pSrfTop)) ; +// pSTM->DoSewing( *pSrfRgt) ; +// pSTM->DoSewing( *pSrfLft) ; +// pSTM->DoSewing( *pSrfBot) ; +// // salvo tolleranza lineare usata e imposto angolo per smooth +// pSTM->SetLinearTolerance( dLinTol) ; +// pSTM->SetSmoothAngle( 20) ; +// // se guida aperta e tappi piatti +// if ( ! bGuideClosed && nCapType == RSCAP_FLAT) { +// // verifico che le due estremità siano chiuse e piatte +// POLYLINEVECTOR vPL ; +// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) +// return nullptr ; +// Plane3d plEnds ; double dArea ; +// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL)) +// return nullptr ; +// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL)) +// return nullptr ; +// // aggiungo il cap sull'inizio +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0])) +// return nullptr ; +// pSci->Invert() ; +// pSTM->DoSewing( *pSci) ; +// // aggiungo il cap sulla fine +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1])) +// return nullptr ; +// pSce->Invert() ; +// pSTM->DoSewing( *pSce) ; +// } +// // se altrimenti guida aperta e tappi arrotondati +// if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { +// // step di rotazione per rispettare la tolleranza +// double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ; +// // aggiungo il cap sull'inizio +// Point3d ptStart ; +// pGuide->GetStartPoint( ptStart) ; +// Vector3d vtStart ; +// pGuide->GetStartDir( vtStart) ; +// vtStart.Rotate( vtNorm, 0, 1) ; +// PolyLine PLStart ; +// PLStart.AddUPoint( 0, ptStart) ; +// PLStart.AddUPoint( 1, ptStart + dDimH / 2 * vtStart) ; +// PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dDimV * vtNorm) ; +// PLStart.AddUPoint( 3, ptStart - dDimV * vtNorm) ; +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) +// return nullptr ; +// pSci->Invert() ; +// pSTM->DoSewing( *pSci) ; +// // aggiungo il cap sulla fine +// Point3d ptEnd ; +// pGuide->GetEndPoint( ptEnd) ; +// Vector3d vtEnd ; +// pGuide->GetEndDir( vtEnd) ; +// vtEnd.Rotate( vtNorm, 0, -1) ; +// PolyLine PLEnd ; +// PLEnd.AddUPoint( 0, ptEnd) ; +// PLEnd.AddUPoint( 1, ptEnd + dDimH / 2 * vtEnd) ; +// PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dDimV * vtNorm) ; +// PLEnd.AddUPoint( 3, ptEnd - dDimV * vtNorm) ; +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) +// return nullptr ; +// pSce->Invert() ; +// pSTM->DoSewing( *pSce) ; +// } +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//static ISurfBezier* +//GetSurfBezierBeveledRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // metodo di calcolo impostato da USE_VORONOI +// +// // verifico che la linea guida sia piana +// Plane3d plGuide ; +// if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) +// return nullptr ; +// // assegno la normale del piano +// Vector3d vtNorm = plGuide.GetVersN() ; +// // determino il punto centrale della sezione +// Point3d ptCen ; +// pGuide->GetStartPoint( ptCen) ; +// ptCen -= dDimV / 2 * vtNorm ; +// // determino se la guida è chiusa +// bool bGuideClosed = pGuide->IsClosed() ; +// // curve di offset +// const int NUM_OFFS = 4 ; +// OffsetCurve vOffsCrv[NUM_OFFS] ; +// double vDist[NUM_OFFS] = { dDimH / 2 - dBevelH, -dDimH / 2 + dBevelH, dDimH / 2, -dDimH / 2} ; +// bool bOk = true ; +// if ( ! USE_VORONOI) { +// future vRes[NUM_OFFS] ; +// for ( int i = 0 ; i < NUM_OFFS ; ++ i) +// vRes[i] = async( launch::async, &OffsetCurve::Make, &vOffsCrv[i], pGuide, vDist[i], ICurve::OFF_FILLET) ; +// bool bOk = true ; +// int nFin = 0 ; +// while ( nFin < NUM_OFFS) { +// for ( int i = 0 ; i < NUM_OFFS ; ++ i) { +// if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) { +// bOk = vRes[i].get() && bOk ; +// ++ nFin ; +// } +// } +// } +// } +// else { +// // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo +// for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i) +// bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ; +// } +// +// if ( ! bOk || +// vOffsCrv[0].GetCurveCount() == 0 || vOffsCrv[1].GetCurveCount() == 0 || +// vOffsCrv[2].GetCurveCount() == 0 || vOffsCrv[3].GetCurveCount() == 0) +// return nullptr ; +// PtrOwner pCrvR( vOffsCrv[0].GetLongerCurve()) ; +// if ( IsNull( pCrvR)) +// return nullptr ; +// PtrOwner pCrvL( vOffsCrv[1].GetLongerCurve()) ; +// if ( IsNull( pCrvL)) +// return nullptr ; +// PtrOwner pCrvRb( vOffsCrv[2].GetLongerCurve()) ; +// if ( IsNull( pCrvRb)) +// return nullptr ; +// pCrvRb->Translate( - dBevelV * vtNorm) ; +// PtrOwner pCrvLb( vOffsCrv[3].GetLongerCurve()) ; +// if ( IsNull( pCrvLb)) +// return nullptr ; +// pCrvLb->Translate( - dBevelV * vtNorm) ; +// // costruisco le parti di superficie +// PtrOwner pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; +// if ( IsNull( pSrfTop)) +// return nullptr ; +// PtrOwner pSrfBot( pSrfTop->Clone()) ; +// if ( IsNull( pSrfBot)) +// return nullptr ; +// pSrfBot->Translate( -dDimV * vtNorm) ; +// pSrfBot->Invert() ; +// PtrOwner pSrfTopR( GetSurfTriMeshRuled( pCrvRb, pCrvR, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; +// if ( IsNull( pSrfTopR)) +// return nullptr ; +// PtrOwner pSrfBotR( pSrfTopR->Clone()) ; +// if ( IsNull( pSrfBotR)) +// return nullptr ; +// pSrfBotR->Mirror( ptCen, vtNorm) ; +// PtrOwner pSrfTopL( GetSurfTriMeshRuled( pCrvL, pCrvLb, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; +// if ( IsNull( pSrfTopL)) +// return nullptr ; +// PtrOwner pSrfBotL( pSrfTopL->Clone()) ; +// if ( IsNull( pSrfBotL)) +// return nullptr ; +// pSrfBotL->Mirror( ptCen, vtNorm) ; +// PtrOwner pSrfRgt( GetSurfTriMeshByExtrusion( pCrvRb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ; +// if ( IsNull( pSrfRgt)) +// return nullptr ; +// pSrfRgt->Invert() ; +// PtrOwner pSrfLft( GetSurfTriMeshByExtrusion( pCrvLb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ; +// if ( IsNull( pSrfLft)) +// return nullptr ; +// // unisco le parti +// int nBuckets = max( 4 * ( pSrfRgt->GetVertexSize() + pSrfLft->GetVertexSize()), 1000) ; +// StmFromTriangleSoup stmSoup ; +// if ( ! stmSoup.Start( nBuckets)) +// return nullptr ; +// stmSoup.AddSurfTriMesh( *pSrfTop) ; +// stmSoup.AddSurfTriMesh( *pSrfTopR) ; +// stmSoup.AddSurfTriMesh( *pSrfTopL) ; +// stmSoup.AddSurfTriMesh( *pSrfRgt) ; +// stmSoup.AddSurfTriMesh( *pSrfLft) ; +// stmSoup.AddSurfTriMesh( *pSrfBotR) ; +// stmSoup.AddSurfTriMesh( *pSrfBotL) ; +// stmSoup.AddSurfTriMesh( *pSrfBot) ; +// PtrOwner pSTM ; +// // se guida aperta e tappi piatti +// if ( ! bGuideClosed && nCapType == RSCAP_FLAT) { +// // completo unione e recupero la superficie risultante +// if ( ! stmSoup.End()) +// return nullptr ; +// pSTM.Set( stmSoup.GetSurf()) ; +// // preparo seconda zuppa di triangoli per inserire i tappi +// StmFromTriangleSoup stmCapSoup ; +// if ( ! stmCapSoup.Start( nBuckets)) +// return nullptr ; +// // verifico che le due estremità siano chiuse e piatte +// POLYLINEVECTOR vPL ; +// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) +// return nullptr ; +// Plane3d plEnds ; double dArea ; +// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) +// return nullptr ; +// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) +// return nullptr ; +// // calcolo il cap sull'inizio +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0])) +// return nullptr ; +// pSci->Invert() ; +// // calcolo il cap sulla fine +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1])) +// return nullptr ; +// pSce->Invert() ; +// // cucio i tappi all'estrusione +// if ( ! pSTM->DoSewing( *pSci) || ! pSTM->DoSewing( *pSce)) +// return nullptr ; +// } +// // se altrimenti guida aperta e tappi arrotondati +// else if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { +// // step di rotazione per rispettare il tipo o la tolleranza +// double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ; +// // aggiungo il cap sull'inizio +// Point3d ptStart ; +// pGuide->GetStartPoint( ptStart) ; +// Vector3d vtStart ; +// pGuide->GetStartDir( vtStart) ; +// vtStart.Rotate( vtNorm, 0, 1) ; +// PolyLine PLStart ; +// PLStart.AddUPoint( 0, ptStart) ; +// PLStart.AddUPoint( 1, ptStart + ( dDimH / 2 - dBevelH) * vtStart) ; +// PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dBevelV * vtNorm) ; +// PLStart.AddUPoint( 3, ptStart + dDimH / 2 * vtStart - ( dDimV - dBevelV) * vtNorm) ; +// PLStart.AddUPoint( 4, ptStart + ( dDimH / 2 - dBevelH) * vtStart - dDimV * vtNorm) ; +// PLStart.AddUPoint( 5, ptStart - dDimV * vtNorm) ; +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) +// return nullptr ; +// pSci->Invert() ; +// stmSoup.AddSurfTriMesh( *pSci) ; +// // aggiungo il cap sulla fine +// Point3d ptEnd ; +// pGuide->GetEndPoint( ptEnd) ; +// Vector3d vtEnd ; +// pGuide->GetEndDir( vtEnd) ; +// vtEnd.Rotate( vtNorm, 0, -1) ; +// PolyLine PLEnd ; +// PLEnd.AddUPoint( 0, ptEnd) ; +// PLEnd.AddUPoint( 1, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd) ; +// PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dBevelV * vtNorm) ; +// PLEnd.AddUPoint( 3, ptEnd + dDimH / 2 * vtEnd - ( dDimV - dBevelV) * vtNorm) ; +// PLEnd.AddUPoint( 4, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd - dDimV * vtNorm) ; +// PLEnd.AddUPoint( 5, ptEnd - dDimV * vtNorm) ; +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) +// return nullptr ; +// pSce->Invert() ; +// stmSoup.AddSurfTriMesh( *pSce) ; +// // completo unione e recupero la superficie risultante +// if ( ! stmSoup.End()) +// return nullptr ; +// pSTM.Set( stmSoup.GetSurf()) ; +// } +// else { +// // completo unione e recupero la superficie risultante +// if ( ! stmSoup.End()) +// return nullptr ; +// pSTM.Set( stmSoup.GetSurf()) ; +// } +// // salvo tolleranza lineare usata e imposto angolo per smooth +// pSTM->SetLinearTolerance( dLinTol) ; +// pSTM->SetSmoothAngle( 20) ; +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( pGuide == nullptr || dBevelH > 0.4 * dDimH || dBevelV > 0.4 * dDimV) +// return nullptr ; +// // determino se sezione squadrata o con smusso +// bool bSharp = ( dBevelH < 100 * EPS_SMALL || dBevelV < 100 * EPS_SMALL) ; +// // eseguo +// if ( bSharp) +// return GetSurfBezierSharpRectSwept( dDimH, dDimV, pGuide, nCapType, dLinTol) ; +// else +// return GetSurfBezierBeveledRectSwept( dDimH, dDimV, dBevelH, dBevelV, pGuide, nCapType, dLinTol) ; +//} +// +////------------------------------------------------------------------------------- +//static ISurfBezier* +//GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // determino se la sezione è chiusa +// bool bSectClosed = pSect->IsClosed() ; +// // determino se la guida è chiusa +// bool bGuideClosed = pGuide->IsClosed() ; +// +// // riferimento all'inizio della linea guida +// Frame3d frStart ; +// Point3d ptStart ; +// pGuide->GetStartPoint( ptStart) ; +// Vector3d vtStart ; +// pGuide->GetStartDir( vtStart) ; +// frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; +// +// // calcolo la polilinea che approssima la sezione +// PolyLine PL ; +// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) +// return nullptr ; +// +// // porto la sezione in questo riferimento e ve la appiattisco +// if ( ! PL.ToLoc( frStart) || ! PL.Flatten()) +// return nullptr ; +// +// // preparo collettore delle superfici componenti +// StmFromTriangleSoup StmFts ; +// if ( ! StmFts.Start()) +// return nullptr ; +// +// // superficie swept +// PtrOwner pPrevCrv ; +// Point3d ptP ; +// bool bPoint = PL.GetFirstPoint( ptP) ; +// while ( bPoint) { +// // nuova curva ( definita dall'Offset ) +// OffsetCurve OffsCrv ; +// if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0) +// return nullptr ; +// PtrOwner pCurrCrv( OffsCrv.GetLongerCurve()) ; +// if ( IsNull( pCurrCrv)) +// return nullptr ; +// pCurrCrv->Translate( ptP.y * frStart.VersY()) ; +// // se esiste la curva precedente, costruisco la rigata ( di tipo minima distanza) +// if ( ! IsNull( pPrevCrv)) { +// PtrOwner pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; +// if ( IsNull( pSr)) +// return nullptr ; +// // inserisco nel collettore +// StmFts.AddSurfTriMesh( *pSr) ; +// } +// // salvo la curva come prossima precedente +// pPrevCrv.Set( pCurrCrv) ; +// // prossimo punto +// bPoint = PL.GetNextPoint( ptP) ; +// } +// +// // recupero la supeficie risultante +// if ( ! StmFts.End()) +// return nullptr ; +// PtrOwner pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ; +// if ( IsNull( pSTM)) +// return nullptr ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// +// // se richiesti caps e sezione chiusa e guida aperta +// if ( bCapEnds && bSectClosed && ! bGuideClosed) { +// // verifico che le due estremità siano chiuse e piatte +// POLYLINEVECTOR vPL ; +// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) +// return nullptr ; +// Plane3d plEnds ; double dArea ; +// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL)) +// return nullptr ; +// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL)) +// return nullptr ; +// // aggiungo il cap sull'inizio +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) +// return nullptr ; +// pSci->ToGlob( frStart) ; +// // unisco +// pSTM->DoSewing( *pSci) ; +// // riferimento alla fine della linea guida +// Frame3d frEnd ; +// Point3d ptEnd ; +// pGuide->GetEndPoint( ptEnd) ; +// Vector3d vtEnd ; +// pGuide->GetEndDir( vtEnd) ; +// frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ; +// // aggiungo il cap sulla fine +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) +// return nullptr ; +// pSce->Invert() ; +// pSce->ToGlob( frEnd) ; +// // unisco +// pSTM->DoSewing( *pSce) ; +// } +// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno +// double dVol ; +// if ( pSTM->GetVolume( dVol) && dVol < 0) +// pSTM->Invert() ; +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//static ISurfBezier* +//GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // determino se la sezione è chiusa +// bool bSectClosed = pSect->IsClosed() ; +// // determino se la guida è chiusa +// bool bGuideClosed = pGuide->IsClosed() ; +// // determino algoritmo da usare per calcolare i riferimenti lungo la curva +// bool bRMF = vtAx.IsSmall() ; +// +// // riferimento all'inizio della linea guida +// Point3d ptStart ; +// pGuide->GetStartPoint( ptStart) ; +// Vector3d vtStart ; +// pGuide->GetStartDir( vtStart) ; +// Frame3d frStart ; +// if ( bRMF) { +// if ( ! frStart.Set( ptStart, vtStart)) +// return nullptr ; +// } +// else { +// Vector3d vtAxX = vtAx ^ vtStart ; +// if ( vtAxX.IsSmall()) { +// vtAxX = FromUprightOrtho( vtAx) ; +// vtAxX.Rotate( vtAx, 0, 1) ; +// } +// if ( ! frStart.Set( ptStart, vtStart, vtAxX)) +// return nullptr ; +// } +// +// // calcolo la polilinea che approssima la sezione +// PolyLine PL ; +// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) +// return nullptr ; +// +// // recupero la sezione dalla PolyLine approssimata come Curva +// PtrOwner pSecLocApprox( CreateBasicCurveComposite()) ; +// if ( IsNull( pSecLocApprox) || +// ! pSecLocApprox->FromPolyLine( PL) || +// ! pSecLocApprox->IsValid()) +// return nullptr ; +// +// // porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida +// PL.ToLoc( frStart) ; +// pSecLocApprox->ToLoc( frStart) ; +// +// // calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita +// FRAME3DVECTOR vFrames ; +// if ( bRMF) { +// RotationMinimizingFrame RMF ; +// if ( ! RMF.Set( pGuide, frStart) || +// ! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty()) +// return nullptr ; +// } +// else { +// RotationXplaneFrame RXF ; +// if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) || +// ! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty()) +// return nullptr ; +// } +// +// // preparo collettore delle superfici componenti +// StmFromTriangleSoup StmFts ; +// if ( ! StmFts.Start()) +// return nullptr ; +// +// // per ogni Frame calcolato, la sezione va roto-traslata lungo la guida +// for ( int i = 0 ; i < int( vFrames.size()) - 1 ; ++ i) { +// +// // definisco la sezione allo step corrente +// PtrOwner pSecCurr( pSecLocApprox->Clone()) ; +// if ( IsNull( pSecCurr) || ! pSecCurr->IsValid()) +// return nullptr ; +// +// // considero la sezione ( in locale ) come vista dal globale +// if ( ! pSecCurr->ToGlob( vFrames[i])) +// return nullptr ; +// +// // definisco la sezione allo step successivo +// PtrOwner pSecSucc( pSecLocApprox->Clone()) ; +// if ( IsNull( pSecSucc) || ! pSecSucc->IsValid()) +// return nullptr ; +// +// // considero la sezione ( in locale ) come vista dal globale +// if ( ! pSecSucc->ToGlob( vFrames[i+1])) +// return nullptr ; +// +// // creo la rigata tra queste due sezioni +// PtrOwner pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ; +// if ( IsNull( pSr) || ! pSr->IsValid()) +// return nullptr ; +// // la inverto +// pSr->Invert() ; +// // inserisco la superficie nel collettore +// StmFts.AddSurfTriMesh( *pSr) ; +// } +// +// // se richiesti caps e sezione chiusa e guida aperta +// if ( bCapEnds && bSectClosed && ! bGuideClosed) { +// +// // aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida ) +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) +// return nullptr ; +// pSci->ToGlob( vFrames.front()) ; +// // aggiungo +// StmFts.AddSurfTriMesh( *pSci) ; +// +// // aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida ) +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) +// return nullptr ; +// pSce->ToGlob( vFrames.back()) ; +// // inverto +// pSce->Invert() ; +// // aggiungo +// StmFts.AddSurfTriMesh( *pSce) ; +// } +// +// // recupero la supeficie risultante +// if ( ! StmFts.End()) +// return nullptr ; +// PtrOwner pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ; +// if ( IsNull( pSTM)) +// return nullptr ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// +// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno +// double dVol ; +// if ( pSTM->GetVolume( dVol) && dVol < 0) +// pSTM->Invert() ; +// +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, +// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( pSect == nullptr || pGuide == nullptr) +// return nullptr ; +// +// bool bIsLine = false ; +// if ( pGuide->GetType() == CRV_LINE) +// bIsLine = true ; +// else { +// const CurveComposite* pCompo = GetBasicCurveComposite( pGuide) ; +// Point3d ptStart, ptEnd ; +// if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd)) +// bIsLine = true ; +// } +// // se la guida è piana +// Plane3d plGuide ; +// if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL)) +// return GetSurfBezierSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ; +// +// // altrimenti swept 3d +// return GetSurfBezierSwept3d( pSect, pGuide, vtAx, bCapEnds, dLinTol) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, const Vector3d& vtAx, +// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica dei parametri +// if ( pSfrSect == nullptr || pGuide == nullptr) +// return nullptr ; +// +// // predispongo collettore superfici componenti +// StmFromTriangleSoup StmSoup ; +// StmSoup.Start() ; +// +// // per ogni loop della superficie, creo una Swept +// for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) { +// for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) { +// // recupero il loop +// PtrOwner pCrvLoop( pSfrSect->GetLoop( nC, nL)) ; +// if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) +// return nullptr ; +// // creo la Trimesh Swept +// PtrOwner pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, vtAx, false, dLinTol)) ; +// if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid()) +// return nullptr ; +// // aggiungo la Swept ricavata al risultato finale ( come triangoli ) +// StmSoup.AddSurfTriMesh( *pStmLoopSwept) ; +// } +// } +// +// // Recupero la superficie +// if ( ! StmSoup.End()) +// return nullptr ; +// PtrOwner pStmSwept( StmSoup.GetSurf()) ; +// if ( IsNull( pStmSwept)) +// return nullptr ; +// +// // se rischiesta chiusura... +// // Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa +// if ( bCapEnds && ! pGuide->IsClosed()) { +// // recupero i loop all'inizio (dalla regione e apportunamente approssimati) +// POLYLINEVECTOR vPLi ; +// for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) { +// for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) { +// vPLi.emplace_back() ; +// if ( ! pSfrSect->ApproxLoopWithLines( nC, nL, dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLi.back())) +// return nullptr ; +// } +// } +// // creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta) +// PtrOwner pSci( CreateSurfTriMesh()) ; +// if ( ! pSci->CreateByRegion( vPLi)) +// return nullptr ; +// pStmSwept->DoSewing( *pSci) ; +// // recupero i loops alla fine +// POLYLINEVECTOR vPLe ; +// if ( ! pStmSwept->GetLoops( vPLe)) +// return nullptr ; +// // creo la superficie alla fine e la attacco +// PtrOwner pSce( CreateSurfTriMesh()) ; +// if ( ! pSce->CreateByRegion( vPLe)) +// return nullptr ; +// // attacco la superficie finale alla swept +// pSce->Invert() ; +// pStmSwept->DoSewing( *pSce) ; +// } +// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno +// double dVol ; +// if ( pStmSwept->GetVolume( dVol) && dVol < 0) +// pStmSwept->Invert() ; +// +// return Release( pStmSwept) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( pSect == nullptr || pGuide == nullptr) +// return nullptr ; +// // determino se la sezione è chiusa +// bool bSectClosed = pSect->IsClosed() ; +// // punto iniziale della sezione e vettore a inizio guida +// Point3d ptStart ; +// if ( ! pSect->GetStartPoint( ptStart)) +// return nullptr ; +// Point3d ptGuide ; +// if ( ! pGuide->GetStartPoint( ptGuide)) +// return nullptr ; +// Vector3d vtDelta = ptStart - ptGuide ; +// // calcolo la polilinea che approssima la guida +// PolyLine PLG ; +// if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG)) +// return nullptr ; +// // determino se la guida è chiusa +// bool bGuideClosed = PLG.IsClosed() ; +// // calcolo la superficie +// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSTM)) +// return nullptr ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// // superficie swept +// PtrOwner pPrevCrv ; +// Point3d ptP ; +// bool bPoint = PLG.GetFirstPoint( ptP) ; +// while ( bPoint) { +// // nuova curva +// PtrOwner pCurrCrv( pSect->Clone()) ; +// if ( IsNull( pCurrCrv)) +// return nullptr ; +// pCurrCrv->Translate( ptP - ptStart + vtDelta) ; +// // se esiste la curva precedente, costruisco la rigata (di tipo minima distanza) +// if ( ! IsNull( pPrevCrv)) { +// PtrOwner pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_ISOPAR, dLinTol)) ; +// if ( IsNull( pSr)) +// return nullptr ; +// pSTM->DoSewing( *pSr) ; +// } +// // salvo la curva come prossima precedente +// pPrevCrv.Set( pCurrCrv) ; +// // prossimo punto +// bPoint = PLG.GetNextPoint( ptP) ; +// } +// // se richiesti caps e sezione chiusa e guida aperta +// if ( bCapEnds && bSectClosed && ! bGuideClosed) { +// // calcolo la polilinea che approssima la sezione +// PolyLine PLS ; +// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLS)) +// return nullptr ; +// // verifico che la sezione sia chiusa e piatta +// Plane3d plSect ; double dArea ; +// if ( PLS.IsClosedAndFlat( plSect, dArea, 100 * EPS_SMALL)) { +// // aggiungo il cap sull'inizio +// PtrOwner pSci( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PLS)) +// return nullptr ; +// pSci->Invert() ; +// Point3d ptGi ; PLG.GetFirstPoint( ptGi) ; +// pSci->Translate( ptGi - ptStart + vtDelta) ; +// pSTM->DoSewing( *pSci) ; +// // aggiungo il cap sulla fine +// PtrOwner pSce( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PLS)) +// return nullptr ; +// Point3d ptGe ; PLG.GetLastPoint( ptGe) ; +// pSce->Translate( ptGe - ptStart + vtDelta) ; +// pSTM->DoSewing( *pSce) ; +// } +// } +// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno +// double dVol ; +// if ( pSTM->GetVolume( dVol) && dVol < 0) +// pSTM->Invert() ; +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( &ptP == nullptr || pCurve == nullptr) +// return nullptr ; +// // calcolo la polilinea che approssima la curva +// PolyLine PL ; +// if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) +// return nullptr ; +// // creo e setto la superficie trimesh +// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; +// if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptP, PL)) +// return nullptr ; +// // salvo tolleranza lineare usata +// pSTM->SetLinearTolerance( dLinTol) ; +// // restituisco la superficie +// return Release( pSTM) ; +//} +// +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//{ +// // verifica parametri +// if ( pCurve1 == nullptr || pCurve2 == nullptr) +// return nullptr ; +// +// // qui anziché fare le polyline converto le curve in bezier! +// // SE NON HO LO STESSO NUMERO DI CURVE COME LO GESTISCO?? +// +// // calcolo la polilinea che approssima la prima curva +// PolyLine PL1 ; +// if ( ! pCurve1->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL1)) +// return nullptr ; +// // calcolo la polilinea che approssima la seconda curva +// PolyLine PL2 ; +// if ( ! pCurve2->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL2)) +// return nullptr ; +// +// +// // creo e setto la superficie trimesh +// PtrOwner pSbz( CreateBasicSurfBezier()) ; +// if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( PL1, PL2, nType)) +// return nullptr ; +// //// salvo tolleranza lineare usata +// //pSbz->SetLinearTolerance( dLinTol) ; +// // restituisco la superficie +// return Release( pSbz) ; +//} \ No newline at end of file diff --git a/SurfBezier.cpp b/SurfBezier.cpp index ad0991d..302de85 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1784,8 +1784,8 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& Vector3d vtDir = pt2D - pt2DPrev ; vtDir.Normalize() ; // se mi accorgo che sto per tracciare un taglio lungo un bordo posso semplicmente evitarlo - if ( (1 - abs(vtDir.x) < EPS_SMALL && (pt2D.y < EPS_SMALL || m_nSpanV * SBZ_TREG_COEFF - pt2D.y < 1)) || // parallelo agli edge 0 e 2 e su uno di questi - (1 - abs(vtDir.y) < EPS_SMALL && (pt2D.x < EPS_SMALL || m_nSpanU * SBZ_TREG_COEFF - pt2D.x < 1))) { // parallello agli edge 1 e 3 e su uno di questi + if ( (1 - abs(vtDir.x) < SQ_EPS_SMALL && (pt2D.y < 1 || m_nSpanV * SBZ_TREG_COEFF - pt2D.y < 1)) || // parallelo agli edge 0 e 2 e su uno di questi + (1 - abs(vtDir.y) < SQ_EPS_SMALL && (pt2D.x < 1 || m_nSpanU * SBZ_TREG_COEFF - pt2D.x < 1))) { // parallello agli edge 1 e 3 e su uno di questi ++ nRejected ; continue ; } @@ -1794,6 +1794,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& dParamH = m_nSpanV * SBZ_TREG_COEFF ; dParamL = m_nSpanU * SBZ_TREG_COEFF ; // sia questo punto che il precedente sono su un edge, ma il segmento che li unisce non è parallelo ad un edge + // ( i punti per periodicità hanno coordinate diverse anche se dovrebbero averle uguali, quindi il segmento attraversa tutto lo spazio parametrico, anche se in realtà è lungo il bordo di chiusura) // potrei star tracciando un taglio sul bordo di chiusura // controllo se sto tracciando una linea che unisce due lati di chiusura, allora in realtà sdtarei tracciando un taglio sull'edge e quindi posso non tracciarlo if ( (abs( vtDir.x) > abs( vtDir.y) && Dist( pt2D, pt2DPrev) > dParamL * 0.5) || @@ -1882,76 +1883,13 @@ struct hash { }; //---------------------------------------------------------------------------- -bool -SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) +ISurfFlatRegion* +SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const { - // faccio l'intersezione della trimesh ausiliaria con il piano posso ottenere: punti, curve 3d e triangoli( coplanari al piano di taglio) - // i punti li escludo - // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim - // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim - - // se necessario calcolo i poli - if ( m_vbPole.empty()) - CalcPoles() ; - - PNTVECTOR vPnt ; - BIPNTVECTOR vBPnt ; - TRIA3DVECTOR vTria ; - IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; - - // concateno le curve 3d - ChainCurves chainC ; - double dToler = EPS_SMALL ; - chainC.Init( false, dToler, int( vBPnt.size())) ; - for ( int i = 0 ; i < int( vBPnt.size()) ; ++ i) { - Vector3d vtDir = vBPnt[i].second - vBPnt[i].first ; - vtDir.Normalize() ; - if ( ! chainC.AddCurve( i + 1, vBPnt[i].first, vtDir, vBPnt[i].second, vtDir)) - return false ; - } - // GESTIONE DELLE CURVE OTTENUTE DALL'INTERSEZIONE - - // recupero i percorsi concatenati - Point3d ptNear = ( vBPnt.empty() ? ORIG : vBPnt[0].first) ; - INTVECTOR vId ; - - // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi - ICRVCOMPOPOVECTOR vpCCOpen ; - ICRVCOMPOPOVECTOR vpCCClosed ; - - while ( chainC.GetChainFromNear( ptNear, false, vId)) { - // creo una curva composita - PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( IsNull( pCrvCompo)) - return false ; - // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita - bool bAdded = true ; - for ( int i = 0 ; i < int( vId.size()) ; ++ i) { - // creo un segmento di retta - ICurveLine* pLine( CreateCurveLine()) ; - if ( pLine == nullptr) - return false ; - // recupero gli estremi (non vanno mai invertiti per opzione di concatenamento) - int nInd = abs( vId[i]) - 1 ; - Point3d ptStart = ( bAdded ? vBPnt[nInd].first : ptNear) ; - Point3d ptEnd = vBPnt[nInd].second ; - // provo ad accodarlo alla composita - bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && - pLine->Set( ptStart, ptEnd)) ; - bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - ptNear = ( bAdded ? ptEnd : ptStart) ; - } - if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, EPS_SMALL, &plPlane)) - return false ; - } - //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { - // qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie // recupero la regione attuale - - PtrOwner pNewTrim( CreateBasicSurfFlatRegion()) ; if ( m_bTrimmed) pNewTrim.Set( GetTrimRegion()->Clone()) ; @@ -2114,7 +2052,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } } - + // devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente // devo quindi trovare la prossima intersezione con un taglio int nInters = -1 ; @@ -2180,6 +2118,78 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } + // aggiungo i loop chiusi + for ( int i = 0 ; i < int( vpCCClosed.size()); ++i ) + sfrContour.AddCurve( Release( vpCCClosed[i])) ; + + PtrOwner pSfrTrimReg( sfrContour.GetSurf()) ; + return Release( pSfrTrimReg) ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) +{ + // faccio l'intersezione della trimesh ausiliaria con il piano posso ottenere: punti, curve 3d e triangoli( coplanari al piano di taglio) + // i punti li escludo + // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim + // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim + + // se necessario calcolo i poli + if ( m_vbPole.empty()) + CalcPoles() ; + + PNTVECTOR vPnt ; + BIPNTVECTOR vBPnt ; + TRIA3DVECTOR vTria ; + IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; + + // concateno le curve 3d + ChainCurves chainC ; + double dToler = EPS_SMALL ; + chainC.Init( false, dToler, int( vBPnt.size())) ; + for ( int i = 0 ; i < int( vBPnt.size()) ; ++ i) { + Vector3d vtDir = vBPnt[i].second - vBPnt[i].first ; + vtDir.Normalize() ; + if ( ! chainC.AddCurve( i + 1, vBPnt[i].first, vtDir, vBPnt[i].second, vtDir)) + return false ; + } + // GESTIONE DELLE CURVE OTTENUTE DALL'INTERSEZIONE + + // recupero i percorsi concatenati + Point3d ptNear = ( vBPnt.empty() ? ORIG : vBPnt[0].first) ; + INTVECTOR vId ; + + // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi + ICRVCOMPOPOVECTOR vpCCOpen ; + ICRVCOMPOPOVECTOR vpCCClosed ; + + while ( chainC.GetChainFromNear( ptNear, false, vId)) { + // creo una curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return false ; + // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita + bool bAdded = true ; + for ( int i = 0 ; i < int( vId.size()) ; ++ i) { + // creo un segmento di retta + ICurveLine* pLine( CreateCurveLine()) ; + if ( pLine == nullptr) + return false ; + // recupero gli estremi (non vanno mai invertiti per opzione di concatenamento) + int nInd = abs( vId[i]) - 1 ; + Point3d ptStart = ( bAdded ? vBPnt[nInd].first : ptNear) ; + Point3d ptEnd = vBPnt[nInd].second ; + // provo ad accodarlo alla composita + bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && + pLine->Set( ptStart, ptEnd)) ; + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, EPS_SMALL, &plPlane)) + return false ; + } + //GESTIONE DEI TRIANGOLI RISULTANTI DALL'INTERSEZIONE StmFromTriangleSoup StmFts ; if ( ! StmFts.Start()) @@ -2197,16 +2207,15 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pNewStm->GetLoops( vPLTria) ; } - // aggiungo i loop chiusi - for ( int i = 0 ; i < int( vpCCClosed.size()); ++i ) - sfrContour.AddCurve( Release( vpCCClosed[i])) ; // aggiungo loop derivati dai triangoli for ( int i = 0 ; i < int( vPLTria.size()); ++i ) { - PtrOwner pCC( CreateCurveComposite()) ; - pCC->FromPolyLine( vPLTria[i]) ; - sfrContour.AddCurve( Release( pCC)) ; + vpCCClosed.emplace_back() ; + vpCCClosed.back()->FromPolyLine( vPLTria[i]) ; } - PtrOwner pSFR( sfrContour.GetSurf()) ; + + // ora posso chiamare la costruzione dello spazio parametrico trimmato + + PtrOwner pSFR( CreateTrimRegionFromCuts( vpCCOpen, vpCCClosed)) ; if ( IsNull( pSFR) || ! pSFR->IsValid()) return false ; @@ -2723,6 +2732,8 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d bool SurfBezier::CalcPoles( void) { + if ( m_vbPole.size() != 0) + return true ; // la funzione identifica se degli edge della superficie non trimmata sono in realtà dei poli for ( int i = 0 ; i < 4 ; ++i) m_vbPole.emplace_back( true) ; @@ -3247,3 +3258,138 @@ SurfBezier::IsPlanar( void) const // nel dubbio restituisco false return false ; } + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateByFlatContour( const PolyLine& PL) +{ + Plane3d plPlane ; + double dArea = 0 ; + if ( ! PL.IsClosedAndFlat( plPlane, dArea, EPS_SMALL)) + return false ; + // creo una superficie piana grande come il box della curva nel suo piano e poi la trimmo + Frame3d frPlane ; + Point3d ptStart ; PL.GetFirstPoint( ptStart) ; + frPlane.Set( ptStart, plPlane.GetVersN()) ; + // recupero il box + BBox3d bboxContour ; + PL.GetLocalBBox( bboxContour) ; + // inizializzo la superficie come una bezier di primo grado formata da una sola patch + int nDegU = 1, nDegV = 1, nSpanU = 1, nSpanV = 1 ; + bool bRat = false ; + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // i punti di controllo sono i quattro vertici della bbox ( che è piana) + Point3d ptBL = bboxContour.GetMin() ; + Point3d ptTR = bboxContour.GetMax() ; + SetControlPoint( 0, ptBL) ; + SetControlPoint( 1, Point3d( ptTR.x, ptBL.y)) ; + SetControlPoint( 2, Point3d( ptBL.x, ptTR.y)) ; + SetControlPoint( 3, ptTR) ; + + // calcolo il corrispondente parametrico del contorno + PtrOwner pCCContour( CreateCurveComposite()) ; + if ( IsNull( pCCContour)) + return false ; + pCCContour->FromPolyLine( PL) ; + + // calcolo gli eventuali poli, necessari per poter chiamare le funzioni di unproject + CalcPoles() ; + ICRVCOMPOPOVECTOR vCCOpen ; + ICRVCOMPOPOVECTOR vCCClosed ; + AddCurveCompoToCuts( pCCContour, vCCOpen, vCCClosed) ; + // creo la regione di trim dai loop di trim + PtrOwner pSfrTrim( CreateTrimRegionFromCuts( vCCOpen, vCCClosed)) ; + if ( IsNull( pSfrTrim) || ! pSfrTrim->IsValid()) + return false ; + SetTrimRegion( *pSfrTrim) ; + + if ( plPlane.GetVersN().z < EPS_SMALL) + Invert() ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateByRegion( const POLYLINEVECTOR& vPL) +{ + return false ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr, bool bDeg3orDeg2) +{ + if ( pCrv == nullptr) + return false ; + // verifico che la curva passata sia una bezier semplice o una composita di bezier + if ( pCrv->GetType() != CRV_COMPO && pCrv->GetType() != CRV_BEZIER) + return false ; + // se composita verifico che curve siano con lo stesso grado e uniformi come tipo + + PtrOwner pCC( CreateCurveComposite()) ; + pCC->AddCurve( pCrv->Clone()) ; + bool bRat = false ; + int nDegU = 1 ; + for ( int i = 0 ; i < pCC->GetCurveCount() ; ++i) { + if ( pCC->GetCurve( i)->GetType() != CRV_BEZIER) + return false ; + const ICurveBezier* pCrvBez = static_cast( pCC->GetCurve( i)) ; + if ( i == 0 ) { + bRat = pCrvBez->IsRational() ; + nDegU = pCrvBez->GetDegree() ; + } + else { + if ( pCrvBez->GetDegree() != nDegU || pCrvBez->IsRational() != bRat) + return false ; + } + } + + // riempio la matrice dei punti di controllo + // parto dalla curva che sto estrudendo e mi alzo progressivamente seguendo il vettore vtExtr + int nDegV = bDeg3orDeg2 ? 3 : 2 ; + int nSpanU = pCC->GetCurveCount() ; + int nSpanV = 1 ; + Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ; + + for ( int k = 0 ; k < nSpanU ; ++k) { + const ICurveBezier* pCrvBezier = static_cast( pCC->GetCurve( k)) ; + for ( int i = 0 ; i < nDegU + 1 ; ++i) { + if ( k != 0 && i == 0) + continue ; + Point3d ptCtrl = pCrvBezier->GetControlPoint( i) ; + + int nInd = k * nDegU + i ; + if ( bRat) { + double dW = pCrvBezier->GetControlWeight( i) ; + SetControlPoint( nInd, ptCtrl, dW) ; + } + else + SetControlPoint( nInd, ptCtrl) ; + } + } + + Vector3d vtStep = vtExtr / nDegV ; + // calcolo il vettore di progressione del singolo step per passare dalla curva di partenza alla curva finale + for ( int j = 1 ; j < nDegV + 1 ; ++j) { + for ( int k = 0 ; k < nSpanU ; ++k) { + for ( int i = 0 ; i < nDegU + 1 ; ++i) { + int nIndPrev = ( j - 1) * ( nDegU * nSpanU + 1) + ( k * nDegU + i) ; + Point3d ptCtrl = GetControlPoint( nIndPrev, nullptr) ; + ptCtrl += vtStep ; + int nInd = j * ( nDegU * nSpanU + 1) + k * nDegU + i ; + if ( bRat) { + double dW = GetControlWeight( i, nullptr) ; + SetControlPoint( nInd, ptCtrl, dW) ; + } + else + SetControlPoint( nInd, ptCtrl) ; + } + } + } + + // aggiorno lo stato + m_nStatus = OK ; + + return true ; +} diff --git a/SurfBezier.h b/SurfBezier.h index c58f9d2..b36f459 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -137,6 +137,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; bool IsPlanar( void) const override ; + bool CreateByFlatContour( const PolyLine& PL) override ; + bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; + bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -189,6 +192,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW double GetCurveOnVApproxLen( double dU) const ; // funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico) bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; + ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ; // restituisce il singolo edge della superficie non trimmata ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ; bool UpdateEdgesFromTree( Tree& tr) const ; From 303a270359d269dbb9e0f2f1ab2c8744ad4a8719 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 13 May 2024 10:27:45 +0200 Subject: [PATCH 04/45] =?UTF-8?q?EgtGeomKernel=20:=20-=20gestione=20grado?= =?UTF-8?q?=20e=20razionalit=C3=A0=20delle=20curve=20convertite=20in=20Bez?= =?UTF-8?q?ier.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CurveAux.cpp | 86 +++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 4f32309..f18f0cf 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -405,28 +405,28 @@ CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) //---------------------------------------------------------------------------- ICurve* -CurveToBezierCurve( const ICurve* pCrv) +CurveToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2, bool bForceRat) { PtrOwner pBezierForm ; switch ( pCrv->GetType()) { case CRV_LINE :{ const ICurveLine* pCrvLine = static_cast( pCrv) ; - pBezierForm.Set( LineToBezierCurve( pCrvLine)) ; + pBezierForm.Set( LineToBezierCurve( pCrvLine, bDeg3OrDeg2, bForceRat)) ; break ; } case CRV_ARC : { const ICurveArc* pCrvArc = static_cast( pCrv) ; - pBezierForm.Set( ArcToBezierCurve( pCrvArc)) ; + pBezierForm.Set( ArcToBezierCurve( pCrvArc, bDeg3OrDeg2)) ; break ; } case CRV_COMPO : { const ICurveComposite* pCrvCompo = static_cast( pCrv) ; - pBezierForm.Set( CompositeToBezierCurve( pCrvCompo)) ; + pBezierForm.Set( CompositeToBezierCurve( pCrvCompo, bDeg3OrDeg2, bForceRat)) ; break ; } case CRV_BEZIER : { const ICurveBezier* pCrvBezier = static_cast( pCrv) ; - pBezierForm.Set( BezierToBasicBezierCurve( pCrvBezier)) ; + pBezierForm.Set( BezierToBasicBezierCurve( pCrvBezier, bDeg3OrDeg2, bForceRat)) ; break ; } default : @@ -439,12 +439,15 @@ CurveToBezierCurve( const ICurve* pCrv) //---------------------------------------------------------------------------- ICurveBezier* -LineToBezierCurve( const ICurveLine* pCrvLine) +LineToBezierCurve( const ICurveLine* pCrvLine, bool bDeg3OrDeg2, bool bForceRat) { PtrOwner pCrvBezier( CreateCurveBezier()) ; // rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali - pCrvBezier->Init( 2, true) ; + int nDeg = bDeg3OrDeg2 ? 3 : 2 ; + pCrvBezier->Init( nDeg, true) ; pCrvBezier->FromLine( *pCrvLine) ; + if ( bForceRat) + pCrvBezier->MakeRational() ; return Release( pCrvBezier) ; } @@ -452,31 +455,35 @@ LineToBezierCurve( const ICurveLine* pCrvLine) ICurve* ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2) { + // una spirale non può essere forzata al grado 2 + // verifico sia un arco const CurveArc* pArc = GetBasicCurveArc( pCrv) ; if ( pArc == nullptr) return nullptr ; // se angolo al centro sotto il limite, basta una curva - if ( ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL && abs( pArc->GetDeltaN()) < EPS_ZERO && ! bDeg3OrDeg2) || - ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL && bDeg3OrDeg2)) { + if ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL) { // creo la curva di Bezier equivalente all'arco - PtrOwner pCrvBez( CreateBasicCurveBezier()) ; + PtrOwner pCrvBez( CreateBasicCurveBezier()) ; if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( *pArc)) return nullptr ; + // se l'arco era piano ed è richiesta una curva di grado 3 allora aumento una volta il grado + if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO) + pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; // restituisco la curva return Release( pCrvBez) ; } // altrimenti curva composita di Bezier else { // creo la curva composita - PtrOwner pCrvCompo( CreateBasicCurveComposite()) ; + PtrOwner pCrvCompo( CreateBasicCurveComposite()) ; if ( IsNull( pCrvCompo)) return nullptr ; // inserisco nella CC le curve di Bezier equivalenti alle parti dell'arco int nParts = (int) ceil( abs( pArc->GetAngCenter()) / ( BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL)) ; - if ( ! bDeg3OrDeg2 && abs( pArc->GetDeltaN()) > EPS_ZERO) - nParts *= 2 ; + //if ( ! bDeg3OrDeg2 && abs( pArc->GetDeltaN()) > EPS_ZERO) + // nParts *= 2 ; nParts = max( nParts, 2) ; for ( int i = 0 ; i < nParts ; ++ i) { // copio l'arco originale @@ -484,9 +491,12 @@ ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2) // lo limito alla parte di interesse cArc.TrimStartEndAtParam( i / double( nParts), ( i + 1) / double( nParts)) ; // creo la curva di Bezier equivalente - PtrOwner pCrvBez( CreateBasicCurveBezier()) ; + PtrOwner pCrvBez( CreateBasicCurveBezier()) ; if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc)) return nullptr ; + // se l'arco era piano ed è richiesta una curva di grado 3 allora aumento una volta il grado + if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO) + pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; // aggiungo la curva di Bezier a quella composita if ( ! pCrvCompo->AddCurve( Release( pCrvBez))) return nullptr ; @@ -501,7 +511,7 @@ ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2) //---------------------------------------------------------------------------- ICurve* -CompositeToBezierCurve( const ICurveComposite* pCC) +CompositeToBezierCurve( const ICurveComposite* pCC, bool bDeg3OrDeg2, bool bForceRat) { // converto tutte le curve in bezier razionali di grado 2 PtrOwner pCCBezier( CreateCurveComposite()) ; @@ -517,14 +527,14 @@ CompositeToBezierCurve( const ICurveComposite* pCC) } else if ( pCC->GetCurve(i)->GetType() == CRV_LINE) { const CurveLine* crLine = GetBasicCurveLine( pCC->GetCurve(i)) ; - ICurve* pCrvBezier = LineToBezierCurve( crLine) ; + ICurve* pCrvBezier = LineToBezierCurve( crLine, bDeg3OrDeg2, bForceRat) ; if ( pCrvBezier == nullptr) return nullptr ; pCrvNew.Set( pCrvBezier) ; } else if ( pCC->GetCurve(i)->GetType() == CRV_BEZIER ) { const CurveBezier* crvBezier = GetBasicCurveBezier( pCC->GetCurve(i)) ; - ICurve* pCrvBezier = BezierToBasicBezierCurve( crvBezier) ; + ICurve* pCrvBezier = BezierToBasicBezierCurve( crvBezier, bDeg3OrDeg2, bForceRat) ; if ( pCrvBezier == nullptr) return nullptr ; pCrvNew.Set( pCrvBezier) ; @@ -537,7 +547,7 @@ CompositeToBezierCurve( const ICurveComposite* pCC) //---------------------------------------------------------------------------- ICurve* -BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier) +BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier, bool bDeg3OrDeg2, bool bForceRat) { // resta da calcolare un errore sull'approssimazione oppure usare la tecnica di spezzare la curva originale in sottocurve e approssimarle con bezier cubiche // per ridurre molto l'errore @@ -547,34 +557,26 @@ BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier) int nDeg = pCrvBezier->GetDegree() ; bool bRat = pCrvBezier->IsRational() ; // se la curva è già nella forma giusta la restituisco - if ( nDeg == 2 && bRat) + int nDegWanted = bDeg3OrDeg2 ? 3 : 2 ; + if ( nDeg == nDegWanted && ( ( ! bRat && ! bForceRat) || bRat)) return Release( pCrvNew) ; - // sennò la riduco di grado fino al 2 - PtrOwner pBasicBezier ( CreateCurveBezier()) ; - pBasicBezier->Init( 2, true) ; - double dW = 1 ; - if ( nDeg == 1) { - Point3d ptStart = pCrvBezier->GetControlPoint( 0) ; - Point3d ptEnd = pCrvBezier->GetControlPoint( 1) ; - pBasicBezier->SetControlPoint( 0, ptStart, dW) ; - pBasicBezier->SetControlPoint( 1, 0.5 * (ptStart + ptEnd), dW) ; - pBasicBezier->SetControlPoint( 2, ptEnd, dW) ; - return Release( pBasicBezier) ; + // sennò mi porto al grado giusto + if ( nDeg < nDegWanted) { + while ( nDeg < nDegWanted) + pCrvNew.Set( BezierIncreaseDegree( pCrvNew)) ; } - while ( nDeg > 2 ) { - pCrvNew.Set( BezierDecreaseDegree( pCrvNew, 1)) ; - if ( IsNull( pCrvNew) || ! pCrvNew->IsValid()) - return nullptr ; - -- nDeg ; - } - for ( int i = 0 ; i < 3 ; ++i) { - Point3d ptCopy = pCrvNew->GetControlPoint( i) ; - if ( bRat) - dW = pCrvNew->GetControlWeight( i) ; - pBasicBezier->SetControlPoint( i, ptCopy, dW) ; + else if ( nDeg > nDegWanted) { + while ( nDeg > nDegWanted) { + pCrvNew.Set( BezierDecreaseDegree( pCrvNew, 1)) ; + if ( IsNull( pCrvNew) || ! pCrvNew->IsValid()) + return nullptr ; + -- nDeg ; + } } + if ( bForceRat) + pCrvNew->MakeRational() ; - return Release( pBasicBezier) ; + return Release( pCrvNew) ; } ICurveBezier* From cc7aa66904ec43b5696060348d2cc866ed6d59d2 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 13 May 2024 10:30:24 +0200 Subject: [PATCH 05/45] EgtGeomKernel : - spostata la funzione CalcRegionPolyLines. --- SfrCreate.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++- StmFromCurves.cpp | 139 ---------------------------------------------- 2 files changed, 136 insertions(+), 140 deletions(-) diff --git a/SfrCreate.cpp b/SfrCreate.cpp index e84ece2..5b3d5ee 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -590,4 +590,139 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId) vId.push_back( pCrv->GetTempProp()) ; } return ( ! vId.empty()) ; -} \ No newline at end of file +} + +//------------------------------------------------------------------------------- +bool +CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, + POLYLINEVECTOR& vPL, Vector3d& vtN) +{ + // se non ho curve, non faccio nulla + if ( int( vpCurve.size()) == 0) + return true ; + + // calcolo le polilinee che approssimano le curve + vPL.resize( vpCurve.size()) ; + for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) { + if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i])) + return false ; + } + + // ricavo versore normale + Plane3d plPlane ; double dArea ; + if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) + return false ; + vtN = plPlane.GetVersN() ; + + typedef std::pair INDAREA ; + std::vector m_vArea ; + // calcolo piano medio e area delle curve + m_vArea.reserve( vPL.size()) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + // calcolo piano medio e area + Plane3d plPlane ; + double dArea ; + if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea)) + return false ; + // verifico che le normali siano molto vicine + if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN)) + return false ; + // assegno il segno all'area secondo il verso della normale + if ( ( plPlane.GetVersN() * vtN) > 0) + m_vArea.emplace_back( i, dArea) ; + else + m_vArea.emplace_back( i, - dArea) ; + } + // ordino in senso decrescente sull'area + sort( m_vArea.begin(), m_vArea.end(), + []( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ; + + // dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive) + Frame3d frRef ; frRef.Set( ORIG, vtN) ; + if ( ! frRef.IsValid()) + return false ; + ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + vCrvCompo[i].Set( CreateCurveComposite()) ; + vCrvCompo[i]->FromPolyLine( vPL[i]) ; + vCrvCompo[i]->ToLoc( frRef) ; + } + + // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle + // successive i loop interni + INTMATRIX vnPLIndMat ; + + // vettore di indici per ordinare le PolyLine + INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ; + for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) + vPL_IndOrder[i] = m_vArea[i].first ; + + // aggiungo le diverse curve + bool bFirstCrv ; + Plane3d plExtLoop ; + double dAreaExtLoop = 0. ; + do { + bFirstCrv = true ; + for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) { + // recupero indice di percorso e verifico sia valido + int j = m_vArea[i].first ; + if ( j < 0) + continue ; + // lo inserisco come esterno... + if ( bFirstCrv) { + vnPLIndMat.push_back({ j}) ; + m_vArea[i].first = -1 ; + dAreaExtLoop = m_vArea[i].second ; + // inverto se necessario + if ( m_vArea[i].second < EPS_SMALL) { + vPL[j].Invert() ; + vCrvCompo[j]->Invert() ; + dAreaExtLoop *= -1 ; + } + bFirstCrv = false ; + } + // ... altrimenti verifico se il loop è interno o no + else { + // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo + // esterno a tutti i loop già inseriti nella riga attuale. + // verifica rispetto loop esterno + IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; + CRVCVECTOR ccClass ; + if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || + ! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) || + ccClass.empty() || ccClass[0].nClass != CRVC_IN) + continue ; + // verifica rispetto ai loop interni + bool bOk = true ; + for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) { + IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ; + CRVCVECTOR ccClass2 ; + if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 || + ! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) || + ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) { + bOk = false ; + break ; + } + } + if ( bOk) { + // inserisco nella matrice + vnPLIndMat.back().push_back( j) ; + m_vArea[i].first = -1 ; + // inverto se necessario + if ( m_vArea[i].second * dAreaExtLoop > 0.) { + vPL[j].Invert() ; + vCrvCompo[j]->Invert() ; + } + } + } + } + } while ( ! bFirstCrv) ; + + // ordino le PolyLine per area + POLYLINEVECTOR vPL_tmp ; + for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i) + vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ; + swap( vPL, vPL_tmp) ; + + return true ; +} diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 156dcca..edd57d9 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -31,10 +31,6 @@ using namespace std ; -//------------------------------------------------------------------------------- -static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, - POLYLINEVECTOR& vPL, Vector3d& vtN) ; - //------------------------------------------------------------------------------- ISurfTriMesh* GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol) @@ -1127,138 +1123,3 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do // restituisco la superficie return Release( pSTM) ; } - -//------------------------------------------------------------------------------- -bool -CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, - POLYLINEVECTOR& vPL, Vector3d& vtN) -{ - // se non ho curve, non faccio nulla - if ( int( vpCurve.size()) == 0) - return true ; - - // calcolo le polilinee che approssimano le curve - vPL.resize( vpCurve.size()) ; - for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) { - if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i])) - return false ; - } - - // ricavo versore normale - Plane3d plPlane ; double dArea ; - if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) - return false ; - vtN = plPlane.GetVersN() ; - - typedef std::pair INDAREA ; - std::vector m_vArea ; - // calcolo piano medio e area delle curve - m_vArea.reserve( vPL.size()) ; - for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { - // calcolo piano medio e area - Plane3d plPlane ; - double dArea ; - if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea)) - return false ; - // verifico che le normali siano molto vicine - if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN)) - return false ; - // assegno il segno all'area secondo il verso della normale - if ( ( plPlane.GetVersN() * vtN) > 0) - m_vArea.emplace_back( i, dArea) ; - else - m_vArea.emplace_back( i, - dArea) ; - } - // ordino in senso decrescente sull'area - sort( m_vArea.begin(), m_vArea.end(), - []( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ; - - // dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive) - Frame3d frRef ; frRef.Set( ORIG, vtN) ; - if ( ! frRef.IsValid()) - return false ; - ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ; - for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { - vCrvCompo[i].Set( CreateCurveComposite()) ; - vCrvCompo[i]->FromPolyLine( vPL[i]) ; - vCrvCompo[i]->ToLoc( frRef) ; - } - - // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle - // successive i loop interni - INTMATRIX vnPLIndMat ; - - // vettore di indici per ordinare le PolyLine - INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ; - for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) - vPL_IndOrder[i] = m_vArea[i].first ; - - // aggiungo le diverse curve - bool bFirstCrv ; - Plane3d plExtLoop ; - double dAreaExtLoop = 0. ; - do { - bFirstCrv = true ; - for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) { - // recupero indice di percorso e verifico sia valido - int j = m_vArea[i].first ; - if ( j < 0) - continue ; - // lo inserisco come esterno... - if ( bFirstCrv) { - vnPLIndMat.push_back({ j}) ; - m_vArea[i].first = -1 ; - dAreaExtLoop = m_vArea[i].second ; - // inverto se necessario - if ( m_vArea[i].second < EPS_SMALL) { - vPL[j].Invert() ; - vCrvCompo[j]->Invert() ; - dAreaExtLoop *= -1 ; - } - bFirstCrv = false ; - } - // ... altrimenti verifico se il loop è interno o no - else { - // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo - // esterno a tutti i loop già inseriti nella riga attuale. - // verifica rispetto loop esterno - IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; - CRVCVECTOR ccClass ; - if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || - ! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) || - ccClass.empty() || ccClass[0].nClass != CRVC_IN) - continue ; - // verifica rispetto ai loop interni - bool bOk = true ; - for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) { - IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ; - CRVCVECTOR ccClass2 ; - if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 || - ! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) || - ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) { - bOk = false ; - break ; - } - } - if ( bOk) { - // inserisco nella matrice - vnPLIndMat.back().push_back( j) ; - m_vArea[i].first = -1 ; - // inverto se necessario - if ( m_vArea[i].second * dAreaExtLoop > 0.) { - vPL[j].Invert() ; - vCrvCompo[j]->Invert() ; - } - } - } - } - } while ( ! bFirstCrv) ; - - // ordino le PolyLine per area - POLYLINEVECTOR vPL_tmp ; - for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i) - vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ; - swap( vPL, vPL_tmp) ; - - return true ; -} From 1d4bccac4b07b541c86642c2681e17643c7447b9 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 13 May 2024 11:34:36 +0200 Subject: [PATCH 06/45] EgtGeomKernel : - aggiunte le funzioni per creare superfici di Bezier da Region e da Screwing. --- SbzFromCurves.cpp | 240 ++++++++++++++++++++++------------------------ SurfBezier.cpp | 131 ++++++++++++++++++++++++- SurfBezier.h | 1 + 3 files changed, 242 insertions(+), 130 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index fe871ab..38d258d 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -34,10 +34,6 @@ using namespace std ; -////------------------------------------------------------------------------------- -//static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, -// POLYLINEVECTOR& vPL, Vector3d& vtN) ; - //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol) @@ -59,27 +55,32 @@ GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol) return Release( pSbz) ; } -////------------------------------------------------------------------------------- -//ISurfBezier* -//GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione///////////////////////////////////////////////// -//{ -// // verifica parametri -// if ( &vpCurve == nullptr || vpCurve.empty()) -// return nullptr ; -// // calcolo le polilinee che approssimano le curve della regione -// POLYLINEVECTOR vPL ; -// Vector3d vtN ; -// if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN)) -// return nullptr ; -// // creo e setto la superficie trimesh -// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL)) -// return nullptr ; -// // salvo tolleranza lineare usata -// pSTM->SetLinearTolerance( dLinTol) ; -// // restituisco la superficie -// return Release( pSTM) ; -//} +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) +{ + // verifica parametri + if ( &vpCurve == nullptr || vpCurve.empty()) + return nullptr ; + // calcolo le polilinee che approssimano le curve della regione + POLYLINEVECTOR vPL ; + Vector3d vtN ; + if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN)) + return nullptr ; + //for ( int i = 0 ; i < int(vpCurve.size()) ; ++i ) { + // PolyLine pl ; + // vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, pl) ; + // vPL.push_back( pl) ; + //} + // creo e setto la superficie di bezier + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByRegion( vPL)) + return nullptr ; + //// salvo tolleranza lineare usata + //pSbz->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} //------------------------------------------------------------------------------- ISurfBezier* @@ -111,7 +112,6 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, } } - //PtrOwner pBezierForm( CurveToBezierCurve( pCurve)) ; PtrOwner pBezierForm( pCurve->Clone()) ; // creo e setto la superficie trimesh @@ -144,15 +144,15 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, } ////------------------------------------------------------------------------------- -//ISurfBezier* -//GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +//ISurfCompo* +//GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) ///// RICHIEDE LE SURF COMPO///////////////// //{ // // verifica parametri // if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr) // return nullptr ; // // se una sola curva, uso la funzione precedente // if ( vpCurve.size() == 1 ) -// return GetSurfTriMeshByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ; +// return GetSurfBezierByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ; // // calcolo le polilinee che approssimano le curve della regione // POLYLINEVECTOR vPL ; // Vector3d vtN ; @@ -168,43 +168,30 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // vPL[i].Invert() ; // } // // creo la prima superficie di estremità -// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL)) +// PtrOwner pSbz1( CreateBasicSurfBezier()) ; +// if ( IsNull( pSbz1) || ! pSbz1->CreateByRegion( vPL)) // return nullptr ; -// // creo la seconda superficie e la unisco alla prima -// { // copio la prima superficie -// SurfTriMesh STM2 = *pSTM ; -// // inverto la prima superficie -// pSTM->Invert() ; -// // traslo la seconda -// STM2.Translate( vtExtr) ; -// // la unisco alla prima -// if ( ! pSTM->DoSewing( STM2)) -// return nullptr ; -// } +// // creo la seconda superficie come copia della prima e poi inverto la prima +// PtrOwner pSbz2( pSbz1->Clone()) ; +// pSbz1->Invert() ; +// // // creo e unisco le diverse superfici di estrusione // for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { // // estrusione -// SurfTriMesh STM2 ; -// if ( ! STM2.CreateByExtrusion( vPL[i], vtExtr)) -// return nullptr ; -// // la unisco alla superficie principale -// if ( ! pSTM->DoSewing( STM2)) +// SurfBezier SbzLat ; +// if ( ! SbzLat.CreateByExtrusion( vPL[i], vtExtr)) // qui mi serve la curva e non la polyline della curva. vuol dire che dalla CalcRegionPolyLines devo farmi restituire anche le curve ordinate // return nullptr ; // } -// // compatto la superficie -// if ( ! pSTM->DoCompacting()) -// return nullptr ; -// // salvo tolleranza lineare usata -// pSTM->SetLinearTolerance( dLinTol) ; +// //// salvo tolleranza lineare usata +// //pSTM->SetLinearTolerance( dLinTol) ; // // restituisco la superficie -// return Release( pSTM) ; +// return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica //} ////------------------------------------------------------------------------------- //ISurfBezier* //GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, -// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// +// bool bCapEnds, double dLinTol) //////// per questa serve la SWEPT////////////////////////////////////////////////////////////////// //{ // // verifica parametri // if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) @@ -255,84 +242,85 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // PL.Invert() ; // } // // creo e setto la superficie trimesh -// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSTM) || ! pSTM->CreateByScrewing( PL, ptAx, vtAx, ANG_FULL, dStepRotDeg, 0)) +// PtrOwner pSbz( CreateBasicSurfBezier()) ; +// if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( PL, ptAx, vtAx, ANG_FULL, dStepRotDeg, 0)) // return nullptr ; // // se superficie risultante chiusa, verifico che la normale sia verso l'esterno // double dVol ; -// if ( pSTM->GetVolume( dVol) && dVol < 0) -// pSTM->Invert() ; -// // salvo tolleranza lineare usata -// pSTM->SetLinearTolerance( dLinTol) ; +// if ( pSbz->GetVolume( dVol) && dVol < 0) +// pSbz->Invert() ; +// //// salvo tolleranza lineare usata +// //pSbz->SetLinearTolerance( dLinTol) ; // // restituisco la superficie -// return Release( pSTM) ; +// return Release( pSbz) ; //} // -////------------------------------------------------------------------------------- -//ISurfBezier* -//GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, -// double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// -//{ -// // verifica parametri -// if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) -// return nullptr ; -// // limite minimo su tolleranza -// dLinTol = max( dLinTol, EPS_SMALL) ; -// // calcolo la polilinea che approssima la curva -// PolyLine PL ; -// if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) -// return nullptr ; -// // calcolo lo step di rotazione -// double dMaxRad = 0 ; -// if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) -// return nullptr ; -// double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; -// // se superficie rototraslata, necessari limiti sulla lunghezza dei segmenti -// if ( abs( dAngRotDeg) > EPS_ANG_SMALL && abs( dMove) > EPS_SMALL){ -// double dLenMax = 2.5 * abs( dMove * dStepRotDeg / dAngRotDeg) ; -// if ( ! PL.AdjustForMaxSegmentLen( dLenMax)) -// return nullptr ; -// } -// // creo e setto la superficie trimesh -// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSTM) || ! pSTM->CreateByScrewing( PL, ptAx, vtAx, dAngRotDeg, dStepRotDeg, dMove)) -// return nullptr ; -// // se richiesti caps -// if ( bCapEnds) { -// // determino se la sezione è chiusa e piatta -// Plane3d plPlane ; double dArea ; -// bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ; -// // determino non sia una semplice rivoluzione -// bool bRevolved = ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL && abs( dMove) < EPS_SMALL) ; -// // se sezione chiusa e piatta e non rivoluzione, posso aggiungere i tappi -// if ( bSectClosedFlat && ! bRevolved) { -// // aggiungo il cap sull'inizio -// PtrOwner pSci( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) -// return nullptr ; -// pSTM->DoSewing( *pSci) ; -// // aggiungo il cap sulla fine -// Vector3d vtMove = vtAx ; -// vtMove.Normalize() ; -// vtMove *= dMove ; -// PL.Translate( vtMove) ; -// PL.Rotate( ptAx, vtAx, dAngRotDeg) ; -// PtrOwner pSce( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) -// return nullptr ; -// pSce->Invert() ; -// pSTM->DoSewing( *pSce) ; -// } -// } -// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno -// double dVol ; -// if ( pSTM->GetVolume( dVol) && dVol < 0) -// pSTM->Invert() ; -// // salvo tolleranza lineare usata -// pSTM->SetLinearTolerance( dLinTol) ; -// // restituisco la superficie -// return Release( pSTM) ; -//} +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, + double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) //// ANCORA DA SISTEMARE//// +{ + // verifica parametri + if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) + return nullptr ; + // limite minimo su tolleranza + dLinTol = max( dLinTol, EPS_SMALL) ; + // calcolo la polilinea che approssima la curva + PolyLine PL ; + if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + return nullptr ; + + // calcolo lo step di rotazione + double dMaxRad = 0 ; + if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) + return nullptr ; + double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; + //// se superficie rototraslata, necessari limiti sulla lunghezza dei segmenti + //if ( abs( dAngRotDeg) > EPS_ANG_SMALL && abs( dMove) > EPS_SMALL){ + // double dLenMax = 2.5 * abs( dMove * dStepRotDeg / dAngRotDeg) ; + // if ( ! PL.AdjustForMaxSegmentLen( dLenMax)) + // return nullptr ; + //} + // creo e setto la superficie bezier + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dStepRotDeg, dMove)) + return nullptr ; + //// se richiesti caps /// richiede la SurfCompo + //if ( bCapEnds) { + // // determino se la sezione è chiusa e piatta + // Plane3d plPlane ; double dArea ; + // bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ; + // // determino non sia una semplice rivoluzione + // bool bRevolved = ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL && abs( dMove) < EPS_SMALL) ; + // // se sezione chiusa e piatta e non rivoluzione, posso aggiungere i tappi + // if ( bSectClosedFlat && ! bRevolved) { + // // aggiungo il cap sull'inizio + // PtrOwner pSci( CreateBasicSurfTriMesh()) ; + // if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) + // return nullptr ; + // pSTM->DoSewing( *pSci) ; + // // aggiungo il cap sulla fine + // Vector3d vtMove = vtAx ; + // vtMove.Normalize() ; + // vtMove *= dMove ; + // PL.Translate( vtMove) ; + // PL.Rotate( ptAx, vtAx, dAngRotDeg) ; + // PtrOwner pSce( CreateBasicSurfTriMesh()) ; + // if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) + // return nullptr ; + // pSce->Invert() ; + // pSTM->DoSewing( *pSce) ; + // } + //} + // se superficie risultante chiusa, verifico che la normale sia verso l'esterno + double dVol ; + if ( pSbz->GetVolume( dVol) && dVol < 0) + pSbz->Invert() ; + //// salvo tolleranza lineare usata + //pSTM->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} // ////------------------------------------------------------------------------------- //static ISurfBezier* diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 302de85..831ce40 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -34,6 +34,7 @@ #include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkCurveComposite.h" +#include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Extern/Eigen/Dense" @@ -3268,9 +3269,6 @@ SurfBezier::CreateByFlatContour( const PolyLine& PL) if ( ! PL.IsClosedAndFlat( plPlane, dArea, EPS_SMALL)) return false ; // creo una superficie piana grande come il box della curva nel suo piano e poi la trimmo - Frame3d frPlane ; - Point3d ptStart ; PL.GetFirstPoint( ptStart) ; - frPlane.Set( ptStart, plPlane.GetVersN()) ; // recupero il box BBox3d bboxContour ; PL.GetLocalBBox( bboxContour) ; @@ -3306,6 +3304,9 @@ SurfBezier::CreateByFlatContour( const PolyLine& PL) if ( plPlane.GetVersN().z < EPS_SMALL) Invert() ; + // aggiorno lo stato + m_nStatus = OK ; + return true ; } @@ -3313,7 +3314,50 @@ SurfBezier::CreateByFlatContour( const PolyLine& PL) bool SurfBezier::CreateByRegion( const POLYLINEVECTOR& vPL) { - return false ; + // le polyline in input devono essere già ordinate per area + // la prima polyline quindi è il loop più esterno + Plane3d plPlane ; + double dArea = 0 ; + if ( ! vPL[0].IsClosedAndFlat(plPlane, dArea, EPS_SMALL) ) + return false ; + // creo una superficie piana grande come il box della curva nel suo piano e poi la trimmo + // recupero il box + BBox3d bboxContour ; + vPL[0].GetLocalBBox(bboxContour) ; + // inizializzo la superficie come una bezier di primo grado formata da una sola patch + int nDegU = 1, nDegV = 1, nSpanU = 1, nSpanV = 1 ; + bool bRat = false ; + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // i punti di controllo sono i quattro vertici della bbox ( che è piana) + Point3d ptBL = bboxContour.GetMin() ; + Point3d ptTR = bboxContour.GetMax() ; + SetControlPoint( 0, ptBL) ; + SetControlPoint( 1, Point3d( ptTR.x, ptBL.y)) ; + SetControlPoint( 2, Point3d( ptBL.x, ptTR.y)) ; + SetControlPoint( 3, ptTR) ; + // creo i vettori dei tagli aperti e chiusi + CalcPoles() ; + ICRVCOMPOPOVECTOR vCCOpen ; + ICRVCOMPOPOVECTOR vCCClosed ; + for ( int i = 0 ; i < int( vPL.size()) ; ++i) { + ICurveComposite* pCC( CreateBasicCurveComposite()) ; + pCC->FromPolyLine( vPL[i]) ; + if ( ! AddCurveCompoToCuts( pCC, vCCOpen, vCCClosed)) + return false ; // o metto un continue? + } + // unisco i tagli e creo la regione di trim + PtrOwner pSfrTrim( CreateTrimRegionFromCuts( vCCOpen, vCCClosed)) ; + if ( IsNull( pSfrTrim) || ! pSfrTrim->IsValid()) + return false ; + SetTrimRegion( *pSfrTrim) ; + + if ( plPlane.GetVersN().z < EPS_SMALL) + Invert() ; + + // aggiorno lo stato + m_nStatus = OK ; + + return true ; } //---------------------------------------------------------------------------- @@ -3393,3 +3437,82 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr, bool return true ; } + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dStepRotDeg, double dMove) +{ + // verifico che l'asse di rotazione sia non nullo + if ( vtAx.IsSmall()) + return false ; + // verifico se solo rivoluzione + bool bOnlyRev = ( abs( dMove) < EPS_SMALL) ; + // verifico che l'angolo di rotazione sia significativo e, se solo rivoluzione, non superi un giro + if ( abs( dAngRotDeg) < EPS_ANG_SMALL) + return false ; + if ( bOnlyRev && abs( dAngRotDeg) > ANG_FULL) + dAngRotDeg = _copysign( ANG_FULL, dAngRotDeg) ; + // verifico se rotazione completa + bool bFullRev = bOnlyRev && ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL) ; + + + //// aggiusto il valore dell'angolo di step /// mi serve lo step??? + //const double MIN_STEP_ROT = 1 ; + //const double MAX_STEP_ROT = 90 ; + //if ( abs( dStepRotDeg) < MIN_STEP_ROT) + // dStepRotDeg = _copysign( MIN_STEP_ROT, dAngRotDeg) ; + //else if ( abs( dStepRotDeg) > MAX_STEP_ROT) + // dStepRotDeg = _copysign( MAX_STEP_ROT, dAngRotDeg) ; + //else + // dStepRotDeg = _copysign( dStepRotDeg, dAngRotDeg) ; + //// calcolo il numero di step + //int nStep = int( dAngRotDeg / dStepRotDeg) ; + //nStep = max( nStep, 1) ; + + // codice che suppone che la curva non tocchi l'asse di rivoluzione ( soprattutto lo start) + // creo la spirale su cui far la rail della curva ( in questo caso sarà la curva di bezier che delimita il bordo sinistro dello spazio parametrico tra il punto P00 e il punto P01) + PtrOwner pSpiral( CreateCurveArc()) ; + Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; + pSpiral->SetCPAN( ptAx, ptStart, dAngRotDeg, dMove, vtAx) ; + // converto in bezier la spirale + PtrOwner pCrvV ( CreateCurveComposite()) ; // converto in curva bezier di grado 3 perché l'arco è una spirale + pCrvV->AddCurve( ArcToBezierCurve( pSpiral,true)) ; + if ( IsNull( pCrvV) || ! pCrvV->IsValid()) + return false ; + int nSpanV = int( pCrvV->GetCurveCount()) ; + int nDegV = ( GetCurveBezier( pCrvV->GetCurve(0)))->GetDegree() ; + // converto in bezier la curva iniziale + PtrOwner pCrvU ( CreateCurveComposite()) ; + pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; + if ( IsNull( pCrvU) || ! pCrvU->IsValid()) + return false ; + int nSpanU = int( pCrvU->GetCurveCount()) ; + int nDegU = ( GetCurveBezier( pCrvU->GetCurve(0)))->GetDegree() ; + // inizializzo la superficie + bool bRat = true ; // perché nella direzione del parametro V ho sicuramente delle razioniali + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // ora posso settare i punti di controllo + // scorro le curve che compongono la spirale + Point3d ptP00 ; pCrvV->GetStartPoint( ptP00) ; + for ( int j = 0 ; j < nSpanV + 1; ++j) { + const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; + for( int z = 0 ; z < nDegV + 1 ; ++z) { + Point3d ptRef = pSubCrvBezV->GetControlPoint( z) ; + double dWRef = pSubCrvBezV->GetControlWeight( z) ; + Vector3d vtStepMove = ptRef - ptP00 ; + // scorro le curve che compongono la curva principale + for ( int k = 0 ; k < nSpanU ; ++k ) { + const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvU->GetCurve( k)) ; + // scorro i punti di controllo della sottocurva + for ( int i = 0 ; i < nDegU + 1 ; ++i) { + Point3d ptCtrl = pSubCrvBezU->GetControlPoint( i) ; + ptCtrl += vtStepMove ; + double dW = pSubCrvBezU->GetControlWeight( i) ; + SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrl, dW * dWRef) ; + } + } + } + } + + return true ; +} diff --git a/SurfBezier.h b/SurfBezier.h index b36f459..2ff120b 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -140,6 +140,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool CreateByFlatContour( const PolyLine& PL) override ; bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ; + bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dStepRotDeg, double dMove) ; public : // IGeoObjRW int GetNgeId( void) const override ; From 247849d112ecc926de6a1be7930d12a5fc1f1070 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 21 May 2024 15:42:57 +0200 Subject: [PATCH 07/45] EgtGeomKernel : - aggiunta la funzione per modificare un singolo peso ad una curva di Bezier. - aggiunta la funzione per lo screwing con una superficie di Bezier. - aggiunto un commento. --- CurveBezier.cpp | 26 ++++++++ CurveBezier.h | 1 + SbzFromCurves.cpp | 14 ++-- SurfBezier.cpp | 163 +++++++++++++++++++++++++++++++++------------- SurfBezier.h | 2 +- SurfTriMesh.cpp | 4 ++ 6 files changed, 157 insertions(+), 53 deletions(-) diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 8fd2aed..c891c78 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -141,6 +141,32 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) return true ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::SetControlWeight( int nInd, double dW) +{ + // verifico validità, razionalità e indice + if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg) + return false ; + + // verifico che il peso non sia nullo o negativo + if ( dW < EPS_SMALL) + return false ; + + // assegno il valore e il peso + m_vWeCtrl[nInd] = dW ; + + // annullo analisi presenza singolarità + m_dParSing = - 2 ; + + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + return true ; +} + //---------------------------------------------------------------------------- bool CurveBezier::FromArc( const ICurveArc& crArc) diff --git a/CurveBezier.h b/CurveBezier.h index e51780a..dfc33fc 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -137,6 +137,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW bool Init( int nDeg, bool bIsRational) override ; bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ; bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ; + bool SetControlWeight( int nInd, double dW) override ; bool FromArc( const ICurveArc& crArc) override ; bool FromLine( const ICurveLine& crLine) override ; int GetDegree( void) const override diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 38d258d..95fa72f 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -254,7 +254,7 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // // restituisco la superficie // return Release( pSbz) ; //} -// + //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, @@ -270,11 +270,11 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) return nullptr ; - // calcolo lo step di rotazione - double dMaxRad = 0 ; - if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) - return nullptr ; - double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; + //// calcolo lo step di rotazione + //double dMaxRad = 0 ; + //if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) + // return nullptr ; + //double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; //// se superficie rototraslata, necessari limiti sulla lunghezza dei segmenti //if ( abs( dAngRotDeg) > EPS_ANG_SMALL && abs( dMove) > EPS_SMALL){ // double dLenMax = 2.5 * abs( dMove * dStepRotDeg / dAngRotDeg) ; @@ -283,7 +283,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector //} // creo e setto la superficie bezier PtrOwner pSbz( CreateBasicSurfBezier()) ; - if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dStepRotDeg, dMove)) + if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove)) return nullptr ; //// se richiesti caps /// richiede la SurfCompo //if ( bCapEnds) { diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 831ce40..bf8e070 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -23,6 +23,7 @@ #include "Tree.h" #include "Triangulate.h" #include "SurfTriMesh.h" +#include "DistPointLine.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkStringUtils3d.h" @@ -3440,7 +3441,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr, bool //---------------------------------------------------------------------------- bool -SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dStepRotDeg, double dMove) +SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) { // verifico che l'asse di rotazione sia non nullo if ( vtAx.IsSmall()) @@ -3452,35 +3453,7 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V return false ; if ( bOnlyRev && abs( dAngRotDeg) > ANG_FULL) dAngRotDeg = _copysign( ANG_FULL, dAngRotDeg) ; - // verifico se rotazione completa - bool bFullRev = bOnlyRev && ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL) ; - - - //// aggiusto il valore dell'angolo di step /// mi serve lo step??? - //const double MIN_STEP_ROT = 1 ; - //const double MAX_STEP_ROT = 90 ; - //if ( abs( dStepRotDeg) < MIN_STEP_ROT) - // dStepRotDeg = _copysign( MIN_STEP_ROT, dAngRotDeg) ; - //else if ( abs( dStepRotDeg) > MAX_STEP_ROT) - // dStepRotDeg = _copysign( MAX_STEP_ROT, dAngRotDeg) ; - //else - // dStepRotDeg = _copysign( dStepRotDeg, dAngRotDeg) ; - //// calcolo il numero di step - //int nStep = int( dAngRotDeg / dStepRotDeg) ; - //nStep = max( nStep, 1) ; - // codice che suppone che la curva non tocchi l'asse di rivoluzione ( soprattutto lo start) - // creo la spirale su cui far la rail della curva ( in questo caso sarà la curva di bezier che delimita il bordo sinistro dello spazio parametrico tra il punto P00 e il punto P01) - PtrOwner pSpiral( CreateCurveArc()) ; - Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; - pSpiral->SetCPAN( ptAx, ptStart, dAngRotDeg, dMove, vtAx) ; - // converto in bezier la spirale - PtrOwner pCrvV ( CreateCurveComposite()) ; // converto in curva bezier di grado 3 perché l'arco è una spirale - pCrvV->AddCurve( ArcToBezierCurve( pSpiral,true)) ; - if ( IsNull( pCrvV) || ! pCrvV->IsValid()) - return false ; - int nSpanV = int( pCrvV->GetCurveCount()) ; - int nDegV = ( GetCurveBezier( pCrvV->GetCurve(0)))->GetDegree() ; // converto in bezier la curva iniziale PtrOwner pCrvU ( CreateCurveComposite()) ; pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; @@ -3488,27 +3461,127 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V return false ; int nSpanU = int( pCrvU->GetCurveCount()) ; int nDegU = ( GetCurveBezier( pCrvU->GetCurve(0)))->GetDegree() ; + + // creo la spirale su cui far la rail della curva ( in questo caso sarà la curva di bezier che delimita il bordo sinistro dello spazio parametrico tra il punto P00 e il punto P01) + PtrOwner pCrvV ( CreateCurveComposite()) ; + // devo trovare un punto che NON sta sull'asse per poter costruire una spirale e sapere quante span in V avrò + DBLVECTOR vdSpiralW ; + bool bFound = false ; + for ( int j = 0 ; j < nSpanU && ! bFound ; ++j) { + const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvU->GetCurve( j)) ; + for ( int i = 0 ; i < nDegU + 1 && ! bFound ; ++i) { + Point3d ptCtrlU = pSubCrvBezU->GetControlPoint( i) ; + DistPointLine dpl( ptCtrlU, ptAx, vtAx, 0, false) ; + if ( ! dpl.IsSmall()) { + PtrOwner pSpiral( CreateCurveArc()) ; + pSpiral->SetCPAN( ptAx, ptCtrlU, dAngRotDeg, dMove, vtAx) ; + // converto in bezier la spirale + pCrvV->AddCurve( ArcToBezierCurve( pSpiral,true)) ; + const ICurveBezier* pFirstBez = GetCurveBezier( pCrvV->GetCurve( 0)) ; + int nDeg = pFirstBez->GetDegree() ; // questo è 3 o 2 + for ( int k = 0 ; k < nDeg + 1 ; ++k) + vdSpiralW.push_back( pFirstBez->GetControlWeight( k)) ; + bFound = true ; + } + } + } + if ( ! bFound) + return false ; + + if ( IsNull( pCrvV) || ! pCrvV->IsValid()) + return false ; + int nSpanV = int( pCrvV->GetCurveCount()) ; + int nDegV = ( GetCurveBezier( pCrvV->GetCurve(0)))->GetDegree() ; // inizializzo la superficie bool bRat = true ; // perché nella direzione del parametro V ho sicuramente delle razioniali Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; // ora posso settare i punti di controllo // scorro le curve che compongono la spirale - Point3d ptP00 ; pCrvV->GetStartPoint( ptP00) ; - for ( int j = 0 ; j < nSpanV + 1; ++j) { - const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; - for( int z = 0 ; z < nDegV + 1 ; ++z) { - Point3d ptRef = pSubCrvBezV->GetControlPoint( z) ; - double dWRef = pSubCrvBezV->GetControlWeight( z) ; - Vector3d vtStepMove = ptRef - ptP00 ; - // scorro le curve che compongono la curva principale - for ( int k = 0 ; k < nSpanU ; ++k ) { - const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvU->GetCurve( k)) ; - // scorro i punti di controllo della sottocurva - for ( int i = 0 ; i < nDegU + 1 ; ++i) { - Point3d ptCtrl = pSubCrvBezU->GetControlPoint( i) ; - ptCtrl += vtStepMove ; - double dW = pSubCrvBezU->GetControlWeight( i) ; - SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrl, dW * dWRef) ; + Point3d ptPrev ; pCrvV->GetStartPoint( ptPrev) ; + Frame3d frRev ; frRev.Set( ptAx, vtAx) ; + PtrOwner pCrvUNew( pCrvU->Clone()) ; + Vector3d vtDirPrev = ptPrev - ptAx ; + vtDirPrev.ToLoc( frRev) ; + + // VERSIONE 1 // c'è qualcosa che non torna, probabilmente dovuto alla razionalità della spirale + //// faccio una rail della curva di base lungo la spirale + //for ( int j = 0 ; j < nSpanV ; ++j) { + // const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; + // for( int z = 0 ; z < nDegV + 1 ; ++z) { + // Point3d ptRef = pSubCrvBezV->GetControlPoint( z) ; + // double dWRef = pSubCrvBezV->GetControlWeight( z) ; + // ptRef *= dWRef ; + // Vector3d vtStepMove = ( ptRef - ptPrev) ; + // pCrvUNew->Translate( vtStepMove) ; + // // ruoto la curva base + // Vector3d vtDirNew = ptRef - ptAx ; + // vtDirNew.ToLoc( frRev) ; + // double dAng = 0 ; + // vtDirPrev.GetAngleXY( vtDirNew, dAng) ; + // pCrvUNew->Rotate( ptRef, vtAx, dAng) ; + // // scorro le curve che compongono la curva principale + // for ( int k = 0 ; k < nSpanU ; ++k ) { + // const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvUNew->GetCurve( k)) ; + // // scorro i punti di controllo della sottocurva + // for ( int i = 0 ; i < nDegU + 1 ; ++i) { + // Point3d ptCtrl = pSubCrvBezU->GetControlPoint( i) ; + // ptCtrl /= dWRef ; + // double dW = pSubCrvBezU->GetControlWeight( i) ; + // SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrl, dW * dWRef) ; + // } + // } + // vtDirPrev = vtDirNew ; + // ptPrev = ptRef ; + // } + //} + + // VERSIONE 2 // funziona + // per ogni punto di controllo della curva di base creo la spirale che rappresenta la screw di quel punto + // scorro le sottocurve della curva di base + for ( int k = 0 ; k < nSpanU ; ++k ) { + const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvUNew->GetCurve( k)) ; + //scorro i punti di controllo + for ( int i = 0 ; i < nDegU + 1 ; ++i) { + if ( k != 0 && i == 0) + continue ; + Point3d ptCtrlU = pSubCrvBezU->GetControlPoint( i) ; + double dWU = pSubCrvBezU->GetControlWeight( i) ; + + PtrOwner pCrvV( CreateCurveComposite()) ; + // verifico se il punto di controllo sta sull'asse + // in tal caso anziché una spirale creo semplicemente una linea lungo l'asse + DistPointLine dpl( ptCtrlU, ptAx, vtAx, 0, false) ; + if ( ! dpl.IsSmall()) { + // creo la spirale e la converto in bezier + PtrOwner pSpiral( CreateCurveArc()) ; + pSpiral->SetCPAN( ptAx, ptCtrlU, dAngRotDeg, dMove, vtAx) ; + ICurve* pSpiralBezier( ArcToBezierCurve( pSpiral)) ; // converto in curva bezier di grado 3 perché l'arco è una spirale + pCrvV->AddCurve( pSpiralBezier) ; + } + else { + // creo un segmento in forma bezier con il giusto numero di span + PtrOwner pCL( CreateBasicCurveLine()) ; + pCL->Set( ptCtrlU, ptCtrlU + vtAx * dMove) ; + double dStep = 1. / nSpanV ; + for ( int j = 0 ; j < nSpanV ; ++j) { + PtrOwner pCLSingleSpan( GetCurveLine( pCL->CopyParamRange( j * dStep, ( j + 1) * dStep))) ; + PtrOwner pCrvBezForm( LineToBezierCurve( pCLSingleSpan,true)) ; + // prima di aggiungere le curve alla composito setto i pesi + for ( int z = 0 ; z < pCrvBezForm->GetDegree() + 1 ; ++z) + pCrvBezForm->SetControlWeight( z, vdSpiralW[z]) ; + pCrvV->AddCurve( Release( pCrvBezForm)) ; + } + } + + // aggiungo i punti di controllo + // scorro le sottocurve della spirale + for ( int j = 0 ; j < nSpanV ; ++j) { + const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; + // scorro i punti di controllo + for( int z = 0 ; z < nDegV + 1 ; ++z) { + double dWV = pSubCrvBezV->GetControlWeight( z) ; + Point3d ptCtrlV = pSubCrvBezV->GetControlPoint( z) ; + SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrlV, dWU * dWV) ; } } } diff --git a/SurfBezier.h b/SurfBezier.h index 2ff120b..c541e39 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -140,7 +140,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool CreateByFlatContour( const PolyLine& PL) override ; bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ; - bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dStepRotDeg, double dMove) ; + bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ; public : // IGeoObjRW int GetNgeId( void) const override ; diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 9075f16..147cdb9 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -2632,6 +2632,8 @@ VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vect ptPc.z = 0 ; ++ nSeg ; // verifico distanza + // se la curva è chiusa oppure è vicina all'asse ( entro EPS_SMALL), ma non ho che sono start o end ad essere sull'asse + // allora dovrò rimaneggiare la polyline if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) { if ( bClosed || ( ! ( nSeg == 1 && AreSamePointApprox( ORIG, ptPp)) && @@ -2750,10 +2752,12 @@ SurfTriMesh::CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Ve // verifico che la polilinea non attraversi l'asse di rivoluzione o lo tocchi in punti interni PolyLine MyPL = PL ; + // commented for debug if ( ! VeryfyPolylineForRevolution( MyPL, ptAx, vtAx) && ! AdjustPolylineForRevolution( MyPL, ptAx, vtAx)) { LOG_ERROR( GetEGkLogger(), "StmCreateByRevolution : polyline inside meets axis") return false ; } + // commented for debug // imposto ricalcolo m_nStatus = ERR ; From 7322bf50346be779c93c13e6548fe231506be80c Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 22 May 2024 12:12:29 +0200 Subject: [PATCH 08/45] EgtGeomKernel : - correzioni alle funzioni per cambiare di grado le curve bezier. --- CurveAux.cpp | 52 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index f18f0cf..e49d057 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -469,7 +469,7 @@ ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2) if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( *pArc)) return nullptr ; // se l'arco era piano ed è richiesta una curva di grado 3 allora aumento una volta il grado - if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO) + if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO && false) // debug pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; // restituisco la curva return Release( pCrvBez) ; @@ -604,15 +604,19 @@ BezierIncreaseDegree(const ICurveBezier* pCrvBezier) double dWcurr ; for ( double i = 1 ; i < nDeg ; ++i) { ptCtrlCurr = pCrvBezier->GetControlPoint( int( i)) ; - Point3d ptNew = ( i / nDeg) * ptCtrlPrev + ( 1 - i / ( nDeg)) * ptCtrlCurr ; + double dAlpha = i / nDeg ; if ( bRat) { dWcurr = pCrvBezier->GetControlWeight( int( i)) ; - double dWnew = ( i / nDeg) * dWprev + ( 1 - i / ( nDeg)) * dWcurr ; + double dWnew = dAlpha * dWprev + ( 1 - dAlpha) * dWcurr ; + Point3d ptNew = dAlpha * ptCtrlPrev * dWprev + ( 1 - dAlpha) * ptCtrlCurr * dWcurr; + ptNew /= dWnew ; pNewBezier->SetControlPoint( int( i), ptNew, dWnew) ; - dWprev = dWnew ; + dWprev = dWcurr ; } - else + else { + Point3d ptNew = dAlpha * ptCtrlPrev + ( 1 - dAlpha) * ptCtrlCurr ; pNewBezier->SetControlPoint( int( i), ptNew) ; + } ptCtrlPrev = ptCtrlCurr ; } // salvo l'ultimo punto @@ -656,30 +660,37 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol) double dAlpha = i / ( nDeg + 1) ; // old è riferito alla curva originale Point3d ptOld = pCrvBezier->GetControlPoint( int( i)) ; - ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ; if ( bRat) { double dWold = pCrvBezier->GetControlWeight( int( i)) ; dWcurr = ( dWold + (- dAlpha * dWprev)) / ( 1 - dAlpha) ; + ptCtrlCurr = ( ptOld * dWold + (- dAlpha * ptCtrlPrev * dWprev)) / ( 1 - dAlpha) ; + ptCtrlCurr /= dWcurr ; pNewBezier->SetControlPoint( int( i), ptCtrlCurr, dWcurr) ; dWprev = dWcurr ; } - else + else { + ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ; pNewBezier->SetControlPoint( int( i), ptCtrlCurr) ; + } ptCtrlPrev = ptCtrlCurr ; } // risolvo il punto di mezzo per il caso nDeg pari if ( ( nDeg + 1) % 2 == 0) { // pari double dAlpha = r / ( nDeg + 1.) ; Point3d ptOld = pCrvBezier->GetControlPoint( r) ; - ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ; + if ( bRat) { double dWold = pCrvBezier->GetControlWeight( r) ; dWcurr = ( dWold + (- dAlpha * dWprev)) / ( 1 - dAlpha) ; + ptCtrlCurr = ( ptOld * dWold + (- dAlpha * ptCtrlPrev * dWprev)) / ( 1 - dAlpha) ; + ptCtrlCurr /= dWcurr ; pNewBezier->SetControlPoint( r, ptCtrlCurr, dWcurr) ; dWprev = dWcurr ; } - else + else { + ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ; pNewBezier->SetControlPoint( r, ptCtrlCurr) ; + } } // salvo l'ultimo punto ptCtrlCurr = pCrvBezier->GetControlPoint( nDeg + 1) ; @@ -696,15 +707,18 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol) for ( double i = nDeg - 1 ; i > r ; --i) { double dAlpha = ( i + 1) / ( nDeg + 1) ; Point3d ptOld = pCrvBezier->GetControlPoint( int( i) + 1) ; - ptCtrlCurr = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ; if ( bRat) { double dWold = pCrvBezier->GetControlWeight( int( i) + 1) ; dWcurr = ( dWold - ( ( 1 - dAlpha) * dWprev)) / dAlpha ; + ptCtrlCurr = ( ptOld * dWold + ( - ( 1 - dAlpha) * ptCtrlPrev * dWprev)) / dAlpha ; + ptCtrlCurr /= dWcurr ; pNewBezier->SetControlPoint( int( i), ptCtrlCurr, dWcurr) ; dWprev = dWcurr ; } - else + else { + ptCtrlCurr = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ; pNewBezier->SetControlPoint( int( i), ptCtrlCurr) ; + } ptCtrlPrev = ptCtrlCurr ; } // risolvo il punto di mezzo per il caso nDeg dispari @@ -715,29 +729,37 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol) double dAlpha = r / ( nDeg + 1.) ; ptCtrlPrev = pNewBezier->GetControlPoint( r - 1) ; Point3d ptOld = pCrvBezier->GetControlPoint( r) ; - Point3d ptL = ( ptOld + ( - dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ; + Point3d ptL ; double dWL = 1 ; if ( bRat) { dWprev = pNewBezier->GetControlWeight( r - 1) ; double dWold =pCrvBezier->GetControlWeight( r) ; dWL = ( dWold - ( dAlpha * dWprev)) / ( 1 - dAlpha) ; + ptL = ( ptOld * dWold + ( - dAlpha * ptCtrlPrev * dWprev)) / ( 1 - dAlpha) ; } + else + ptL = ( ptOld + ( - dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ; // punto di destra dAlpha = ( r + 1.) / ( nDeg + 1.) ; ptCtrlPrev = pNewBezier->GetControlPoint( r + 1) ; ptOld = pCrvBezier->GetControlPoint( r + 1) ; double dWR = 1 ; + Point3d ptR ; if ( bRat) { dWprev = pNewBezier->GetControlWeight( r + 1) ; double dWold =pCrvBezier->GetControlWeight( r + 1) ; dWR = ( dWold - ( ( 1 - dAlpha) * dWprev)) / dAlpha ; + ptR = ( ptOld * dWold + ( - ( 1 - dAlpha) * ptCtrlPrev * dWprev)) / dAlpha ; } - Point3d ptR = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ; + else + ptR = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ; // calcolo il punto di mezzo e lo aggiungo Point3d ptNew = ( ptL + ptR) / 2 ; - double dWnew = ( dWL + dWR) / 2 ; - if ( bRat) + if ( bRat) { + double dWnew = ( dWL + dWR) / 2 ; + ptNew /= dWnew ; pNewBezier->SetControlPoint( r, ptNew, dWnew) ; + } else pNewBezier->SetControlPoint( r, ptNew) ; dErr = Dist( ptL, ptR) ; From 77d3fcc7afce83b8035854e385dbe6bcbc8112df Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 22 May 2024 12:13:15 +0200 Subject: [PATCH 09/45] EgtGeomKernel : - aggiunta la funzione per il revolve con superfici di Bezier. --- SbzFromCurves.cpp | 135 +++++++++++++++++++++++----------------------- SurfBezier.cpp | 13 ++++- 2 files changed, 81 insertions(+), 67 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 95fa72f..3bf3c38 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -188,72 +188,75 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica //} -////------------------------------------------------------------------------------- -//ISurfBezier* -//GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, -// bool bCapEnds, double dLinTol) //////// per questa serve la SWEPT////////////////////////////////////////////////////////////////// -//{ -// // verifica parametri -// if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) -// return nullptr ; -// // limite minimo su tolleranza -// dLinTol = max( dLinTol, EPS_SMALL) ; -// // calcolo la polilinea che approssima la curva -// PolyLine PL ; -// if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) -// return nullptr ; -// // calcolo lo step di rotazione -// double dMaxRad = 0 ; -// if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) -// return nullptr ; -// double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; -// // se richiesta chiusura degli estremi -// if ( bCapEnds && ! PL.IsClosed()) { -// Vector3d vtAxN = vtAx ; -// vtAxN.Normalize() ; -// double dPosIni = 0, dPosFin = 0 ; -// Point3d ptP ; -// // proietto l'ultimo punto sull'asse di rotazione -// if ( PL.GetLastPoint( ptP)) { -// dPosFin = ( ptP - ptAx) * vtAxN ; -// Point3d ptPOnAx = ptAx + dPosFin * vtAxN ; -// // se non giace sull'asse, aggiungo il punto proiettato -// if ( ! AreSamePointApprox( ptP, ptPOnAx)) { -// double dU ; -// PL.GetLastU( dU) ; -// PL.AddUPoint( ( dU + 1), ptPOnAx) ; -// } -// } -// // inverto la polilinea -// PL.Invert() ; -// // proietto l'ultimo punto (era il primo) sull'asse di rotazione -// if ( PL.GetLastPoint( ptP)) { -// dPosIni = ( ptP - ptAx) * vtAxN ; -// Point3d ptPOnAx = ptAx + dPosIni * vtAxN ; -// // se non giace sull'asse, aggiungo il punto proiettato -// if ( ! AreSamePointApprox( ptP, ptPOnAx)) { -// double dU ; -// PL.GetLastU( dU) ; -// PL.AddUPoint( ( dU + 1), ptPOnAx) ; -// } -// } -// // decido se reinvertire la polilinea -// if ( dPosFin > dPosIni) -// PL.Invert() ; -// } -// // creo e setto la superficie trimesh -// PtrOwner pSbz( CreateBasicSurfBezier()) ; -// if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( PL, ptAx, vtAx, ANG_FULL, dStepRotDeg, 0)) -// return nullptr ; -// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno -// double dVol ; -// if ( pSbz->GetVolume( dVol) && dVol < 0) -// pSbz->Invert() ; -// //// salvo tolleranza lineare usata -// //pSbz->SetLinearTolerance( dLinTol) ; -// // restituisco la superficie -// return Release( pSbz) ; -//} +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, + bool bCapEnds, double dLinTol) +{ + // verifica parametri + if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) + return nullptr ; + // limite minimo su tolleranza + dLinTol = max( dLinTol, EPS_SMALL) ; + //// calcolo la polilinea che approssima la curva + //PolyLine PL ; + //if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + // return nullptr ; + //// calcolo lo step di rotazione + //double dMaxRad = 0 ; + //if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) + // return nullptr ; + //double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; + + + //// se richiesta chiusura degli estremi + //if ( bCapEnds && ! PL.IsClosed()) { // serve la SURFCOMPO + // Vector3d vtAxN = vtAx ; + // vtAxN.Normalize() ; + // double dPosIni = 0, dPosFin = 0 ; + // Point3d ptP ; + // // proietto l'ultimo punto sull'asse di rotazione + // if ( PL.GetLastPoint( ptP)) { + // dPosFin = ( ptP - ptAx) * vtAxN ; + // Point3d ptPOnAx = ptAx + dPosFin * vtAxN ; + // // se non giace sull'asse, aggiungo il punto proiettato + // if ( ! AreSamePointApprox( ptP, ptPOnAx)) { + // double dU ; + // PL.GetLastU( dU) ; + // PL.AddUPoint( ( dU + 1), ptPOnAx) ; + // } + // } + // // inverto la polilinea + // PL.Invert() ; + // // proietto l'ultimo punto (era il primo) sull'asse di rotazione + // if ( PL.GetLastPoint( ptP)) { + // dPosIni = ( ptP - ptAx) * vtAxN ; + // Point3d ptPOnAx = ptAx + dPosIni * vtAxN ; + // // se non giace sull'asse, aggiungo il punto proiettato + // if ( ! AreSamePointApprox( ptP, ptPOnAx)) { + // double dU ; + // PL.GetLastU( dU) ; + // PL.AddUPoint( ( dU + 1), ptPOnAx) ; + // } + // } + // // decido se reinvertire la polilinea + // if ( dPosFin > dPosIni) + // PL.Invert() ; + //} + + // creo e setto la superficie trimesh + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, ANG_FULL, 0)) + return nullptr ; + // se superficie risultante chiusa, verifico che la normale sia verso l'esterno + double dVol ; + if ( pSbz->GetVolume( dVol) && dVol < 0) + pSbz->Invert() ; + //// salvo tolleranza lineare usata + //pSbz->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} //------------------------------------------------------------------------------- ISurfBezier* diff --git a/SurfBezier.cpp b/SurfBezier.cpp index bf8e070..0c58eb5 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3558,7 +3558,7 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V ICurve* pSpiralBezier( ArcToBezierCurve( pSpiral)) ; // converto in curva bezier di grado 3 perché l'arco è una spirale pCrvV->AddCurve( pSpiralBezier) ; } - else { + else if ( dMove > EPS_SMALL){ // creo un segmento in forma bezier con il giusto numero di span PtrOwner pCL( CreateBasicCurveLine()) ; pCL->Set( ptCtrlU, ptCtrlU + vtAx * dMove) ; @@ -3572,6 +3572,17 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V pCrvV->AddCurve( Release( pCrvBezForm)) ; } } + // se sto facendo una rivoluzione ( dMove == 0) e ho un punto di controllo sull'asse allora ho un polo + // devo aggiungere sempre lo stesso punto per tutta la riga della matrice dei punti di controllo, con i pesi giusti + else { + PtrOwner pCrvBezier( CreateCurveBezier()) ; + pCrvBezier->Init( nDegV, bRat) ; + for ( int z = 0 ; z < nDegV + 1 ; ++z) { + pCrvBezier->SetControlPoint( z, ptCtrlU, vdSpiralW[z]) ; + } + for ( int j = 0 ; j < nSpanV ; ++j) + pCrvV->AddCurve( pCrvBezier->Clone()) ; + } // aggiungo i punti di controllo // scorro le sottocurve della spirale From 3e16c4b56c6f2498936b6764d85ef0a444282fee Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 23 May 2024 11:11:14 +0200 Subject: [PATCH 10/45] EgtGeomKernel : - aggiunti dei commenti. --- SbzFromCurves.cpp | 2 +- SurfBezier.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 3bf3c38..1459484 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -191,7 +191,7 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, - bool bCapEnds, double dLinTol) + bool bCapEnds, double dLinTol) // con l'aggiunta delle SURFCOMPO posso gestire anche i cap e curve che attraversano l'asse { // verifica parametri if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 0c58eb5..a6f1eab 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3464,7 +3464,7 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V // creo la spirale su cui far la rail della curva ( in questo caso sarà la curva di bezier che delimita il bordo sinistro dello spazio parametrico tra il punto P00 e il punto P01) PtrOwner pCrvV ( CreateCurveComposite()) ; - // devo trovare un punto che NON sta sull'asse per poter costruire una spirale e sapere quante span in V avrò + // devo trovare un punto che NON stia sull'asse per poter costruire una spirale e sapere quante span in V avrò DBLVECTOR vdSpiralW ; bool bFound = false ; for ( int j = 0 ; j < nSpanU && ! bFound ; ++j) { From dc082d495efe554fc8ba3a6623c350b4b8c42763 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 24 May 2024 11:30:04 +0200 Subject: [PATCH 11/45] EgtGeomKernel : - aggiunta limitazione alla creazione di una surf bezier tramite revolve nel caso in cui la curva attraversi l'asse di rivoluzione. --- SbzFromCurves.cpp | 2 +- SurfBezier.cpp | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 1459484..9e0bab1 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -261,7 +261,7 @@ GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3 //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, - double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) //// ANCORA DA SISTEMARE//// + double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) { // verifica parametri if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index a6f1eab..2372437 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -23,7 +23,6 @@ #include "Tree.h" #include "Triangulate.h" #include "SurfTriMesh.h" -#include "DistPointLine.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkStringUtils3d.h" @@ -34,6 +33,7 @@ #include "/EgtDev/Include/EGkChainCurves.h" #include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" @@ -3454,6 +3454,30 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V if ( bOnlyRev && abs( dAngRotDeg) > ANG_FULL) dAngRotDeg = _copysign( ANG_FULL, dAngRotDeg) ; + // se sto facendo una rivoluzione e la curva è piana faccio un controllo + // se la curva attraversa l'asse allora mi fermo + if ( dMove < EPS_SMALL ) { + Plane3d plPlane ; + if ( pCurve->IsFlat(plPlane, false, EPS_SMALL) ) { + PtrOwner pAx( CreateCurveLine()) ; + pAx->Set( ptAx - vtAx * 5e5, ptAx + vtAx * 5e5) ; + IntersCurveCurve icc( *pCurve, *pAx) ; + Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; + Point3d ptEnd ; pCurve->GetStartPoint( ptEnd) ; + int nPrevType = 0 ; + for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i) { + IntCrvCrvInfo iccInfo ; + icc.GetIntCrvCrvInfo( i, iccInfo) ; + // se è il punto di inizio o di fine va bene e procedo + if ( AreSamePointApprox( ptStart, iccInfo.IciA[0].ptI) || AreSamePointApprox( ptEnd, iccInfo.IciA[0].ptI)) + continue ; + // se la curva oltrepassa l'asse allora mi fermo, se tocca l'asse, ma resta dallo stesso lato, allora vado avanti + if ( iccInfo.IciA->nPrevTy != iccInfo.IciA->nNextTy) + return nullptr ; + } + } + } + // converto in bezier la curva iniziale PtrOwner pCrvU ( CreateCurveComposite()) ; pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; From ffd714d06976ab33bfb628f7f5048e558a546aa0 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 24 May 2024 12:13:25 +0200 Subject: [PATCH 12/45] EgtGeomKernel : - cambiato il nome ad una funzione. --- SbzStandard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SbzStandard.cpp b/SbzStandard.cpp index 5dd2cbe..f01903a 100644 --- a/SbzStandard.cpp +++ b/SbzStandard.cpp @@ -22,7 +22,7 @@ using namespace std ; //------------------------------------------------------------------------------- ISurfBezier* -CreateBezierSphere( const Point3d& ptCenter, double dR) +GetSurfBezierSphere( const Point3d& ptCenter, double dR) { // creo una superficie di Bezier di grado 2 con 45 punti di controllo PtrOwner pSrfBez( CreateSurfBezier()) ; From ef5c67a4d5cf997eea378897835161061ec45375 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 28 May 2024 16:23:58 +0200 Subject: [PATCH 13/45] EgtGeomKernel : - aggiunti commenti - aggiunte modifiche da implementare ulteriormente per la trinagolazione delle sup bilineari. --- Tree.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 20e7574..51fb1a0 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -21,6 +21,7 @@ #include "SurfFlatRegion.h" #include "IntersLineLine.h" #include "AdjustLoops.h" +#include "/EgtDev/Include/EGkDistLineLine.h" #include "/EgtDev/Include/EGkPolyLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkCurve.h" @@ -750,6 +751,24 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ; dCurvV = Dist( ptV, ptPSrf) ; dCurvU = Dist( ptU, ptPSrf) ; + + // devo calcolare anche il twist, in caso di bordi rettilinei ( superficie di grado maggiore di 1, ma che in realtà è una bilineare) + // NON posso guardare la distanza tra il punto medio delle diagonali e il punto centrale della cella ( uLoc = 0.5, vLoc = 0.5) + // posso guardare la distanza tra le due diagonali + Point3d ptP00, ptP10, ptP11, ptP01 ; + // distanza reale tra i vertici della cella + ptP00 = m_mVert[nCToSplit][0] ; + ptP10 = m_mVert[nCToSplit][1] ; + ptP11 = m_mVert[nCToSplit][2] ; + ptP01 = m_mVert[nCToSplit][3] ; + + // da implementare!!!!! serve una valutazione più fine, sennò approssimo la superficie in modo troppo grossolano!!!! + DistLineLine dll( ptP00, ptP11, ptP10, ptP01, true, true) ; + double dDist = 0 ; dll.GetDist( dDist) ; + if ( dDist > max(dCurvU, dCurvV) ) { + // devo decidere in quale direzione splittare + // dovrei capire in quale delle due direzioni è più torta la superficie + } } // faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e // se sto ancora guardando una cella abbastanza grande @@ -802,7 +821,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) bVert = true ; } m_mTree[nCToSplit].SetSplitDirVert( bVert) ; - Point3d ptP00, ptP10, ptP11, ptP01 ; + Point3d ptP00, ptP10, ptP11, ptP01 ; // distanza reale tra i vertici della cella ptP00 = m_mVert[nCToSplit][0] ; ptP10 = m_mVert[nCToSplit][1] ; @@ -953,7 +972,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) nCToSplit = m_mTree[nCToSplit].m_nChild1 ; } } - Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà + Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà // probabilmente mi servirà salvare nella cella il livello di profondità } // bilineare else { @@ -972,7 +991,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) double dLen3 = Dist( ptP00, ptP01) ; bool bVert = false ; - // calcolo in quale direzione è meglio dividere in base allo stretch + // calcolo in quale direzione è meglio dividere in base allo stretch // in realtà visto che non parametro rispetto alla dimensione nel parametrico, così mi trovo a dividere con un quad-tree Point3d ptPSrfU, ptPSrfV ; double dU = 0, dV = 0 ; double dDistU = 0, dDistV = 0 ; @@ -1035,6 +1054,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } else { dErr = 1. / 4. * ( ( ptP00 - ptP01) + ( ptP11 - ptP10)).Len() ; + //int dErr2 = 1. / 4. * ( ( ptP10 - ptP01) + ( ptP11 - ptP00)).Len() ; //correzione che mi verrebbe intuitiva, ma che fa dividere la superficie molto di più ( probabilmente troppo)!! quindi probabilmente sbagliata } // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) { From eaf11386244248914061b77338086859c34d8038 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 28 May 2024 16:25:43 +0200 Subject: [PATCH 14/45] EgtGeomKernel : - aggiunte le funzioni per creare rigate come superfici di Bezier - piccole modifiche. --- SurfBezier.cpp | 372 ++++++++++++++++++++++++++++++++++++++++++++++++- SurfBezier.h | 2 + 2 files changed, 370 insertions(+), 4 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 2372437..65087f1 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -39,7 +39,6 @@ #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Extern/Eigen/Dense" -#include using namespace std ; @@ -1542,6 +1541,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const else { //Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; Tree.BuildTree( dTol, dSideMin) ; + //Tree.BuildTree( 1, 5) ; //debug } if ( ! Tree.GetPolygons( vvPL)) continue ; @@ -2058,7 +2058,7 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE // devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente // devo quindi trovare la prossima intersezione con un taglio int nInters = -1 ; - double dNextCut = numeric_limits::infinity() ; + double dNextCut = INFINITO ; double dEndCurrentCut ; for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) { // se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop @@ -2079,7 +2079,7 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE } } if ( nInters == -1) { - dNextCut = numeric_limits::infinity() ; + dNextCut = INFINITO ; for ( const auto& pair : mInters) { if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { for ( int i = 0 ; i < int(pair.second.size()); ++i ) { @@ -3480,7 +3480,11 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V // converto in bezier la curva iniziale PtrOwner pCrvU ( CreateCurveComposite()) ; - pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; + // se la curva è già una bezier singola la tengo, sennò la converto + if ( pCurve->GetType() != CRV_BEZIER) + pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; + else + pCrvU->AddCurve( pCurve->Clone()) ; if ( IsNull( pCrvU) || ! pCrvU->IsValid()) return false ; int nSpanU = int( pCrvU->GetCurveCount()) ; @@ -3624,3 +3628,363 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V return true ; } + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) +{ + // converto in bezier la curva iniziale + PtrOwner pCrvU ( CreateCurveComposite()) ; + // se la curva è già una bezier singola la tengo, sennò la converto + if ( pCurve->GetType() != CRV_BEZIER) + pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; + else + pCrvU->AddCurve( pCurve->Clone()) ; + if ( IsNull( pCrvU) || ! pCrvU->IsValid()) + return false ; + // recupero span e grado nel parametro U + int nSpanU = int( pCrvU->GetCurveCount()) ; + int nDegU = ( GetCurveBezier( pCrvU->GetCurve(0)))->GetDegree() ; + bool bRat = (GetCurveBezier( pCrvU->GetCurve(0)))->IsRational() ; + // in V decido che la funzione è una patch di grado 1 + int nSpanV = 1 ; + int nDegV = 1 ; + // inizializzo la curva e aggiungo i punti di controllo + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // scorro le patch nel parametro U + for ( int k = 0 ; k < nSpanU ; ++k) { + const ICurveBezier* pSubCrvU = GetCurveBezier( pCrvU->GetCurve( k)) ; + // scorro i punti di controllo in U + for ( int i = 0 ; i < nDegU + 1 ; ++i ) { + + double dW = pSubCrvU->GetControlWeight( i) ; + Point3d ptCtrl = i == 0 ? pSubCrvU->GetControlPoint( i) : pt ; + // scorro sul parametro V // do per scontato di avere una patch di grado 1 ( quindi nel parametro V ho solo due punti) + for ( int j = 0 ; j < nDegV + 1 ; ++j) { + if ( ! bRat) + SetControlPoint( nDegU * k + i, j, ptCtrl) ; + else + SetControlPoint( nDegU * k + i, j , ptCtrl, dW) ; + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nRuledType) +{ + // converto in bezier la curva iniziale + PtrOwner pCrvU0 ( CreateCurveComposite()) ; + // se la curva è già una bezier singola la tengo, sennò la converto + if ( pCurve0->GetType() != CRV_BEZIER) { + // se è una compo controllo che siano già tutte bezier + bool bAlreadyBez = true ; + if ( pCurve0->GetType() == CRV_COMPO) { + const ICurveComposite* pCC0 = GetBasicCurveComposite( pCurve0) ; + for ( int i = 0 ; i < pCC0->GetCurveCount() ; ++i) { + if ( pCC0->GetCurve( i)->GetType() != CRV_BEZIER) { + bAlreadyBez = false ; + break ; + } + } + } + else + bAlreadyBez = false ; + if ( ! bAlreadyBez) + pCrvU0->AddCurve( CurveToBezierCurve( pCurve0)) ; + else + pCrvU0->AddCurve( pCurve0->Clone()) ; + } + else + pCrvU0->AddCurve( pCurve0->Clone()) ; + if ( IsNull( pCrvU0) || ! pCrvU0->IsValid()) + return false ; + // recupero span e grado nel parametro U + int nSpanU0 = int( pCrvU0->GetCurveCount()) ; + int nDegU0 = ( GetCurveBezier( pCrvU0->GetCurve(0)))->GetDegree() ; + bool bRat0 = (GetCurveBezier( pCrvU0->GetCurve(0)))->IsRational() ; + // se la curva è già una bezier singola la tengo, sennò la converto + PtrOwner pCrvU1 ( CreateCurveComposite()) ; + // se la curva è già una bezier singola la tengo, sennò la converto + if ( pCurve1->GetType() != CRV_BEZIER) { + // se è una compo controllo che siano già tutte bezier + bool bAlreadyBez = true ; + if ( pCurve1->GetType() == CRV_COMPO) { + const ICurveComposite* pCC1 = GetBasicCurveComposite( pCurve1) ; + for ( int i = 0 ; i < pCC1->GetCurveCount() ; ++i) { + if ( pCC1->GetCurve( i)->GetType() != CRV_BEZIER) { + bAlreadyBez = false ; + break ; + } + } + } + else + bAlreadyBez = false ; + if ( ! bAlreadyBez) + pCrvU1->AddCurve( CurveToBezierCurve( pCurve1)) ; + else + pCrvU1->AddCurve( pCurve1->Clone()) ; + } + else + pCrvU1->AddCurve( pCurve1->Clone()) ; + // recupero span e grado nel parametro U + int nSpanU1 = int( pCrvU1->GetCurveCount()) ; + int nDegU1 = ( GetCurveBezier( pCrvU1->GetCurve(0)))->GetDegree() ; + bool bRat1 = (GetCurveBezier( pCrvU1->GetCurve(0)))->IsRational() ; + //// se non ho lo stesso numero di span nelle due curve devo capire come gestire il caso. + //// per il momento non implementato + //if ( nSpanU0 != nSpanU1) + // return nullptr ; + // se le due curve hanno grado diverso allora aumento il grado di quella con grado inferiore + if ( nDegU0 != nDegU1) { + while ( nDegU0 < nDegU1) { + ICurveComposite* pCC( CreateCurveComposite()) ; + for( int k = 0 ; k < nSpanU0 ; ++k) + pCC->AddCurve( BezierIncreaseDegree( GetCurveBezier( pCrvU0->GetCurve( k)))) ; + ++nDegU0 ; + pCrvU0.Set( pCC) ; + } + while ( nDegU0 > nDegU1) { + ICurveComposite* pCC( CreateCurveComposite()) ; + for( int k = 0 ; k < nSpanU0 ; ++k) + pCC->AddCurve( BezierIncreaseDegree( GetCurveBezier( pCrvU1->GetCurve( k)))) ; + ++nDegU1 ; + pCrvU1.Set( pCC) ; + } + } + // omogenizzo la razionalità + if ( bRat0 != bRat1) { + if ( ! bRat0) { + ICurveComposite* pCC( CreateCurveComposite()) ; + for ( int k = 0 ; k < nSpanU0 ; ++k) { + ICurveBezier* pCrvBez = GetCurveBezier( pCrvU0->GetCurve( k)->Clone()) ; + pCrvBez->MakeRational() ; + pCC->AddCurve( pCrvBez) ; + } + pCrvU0.Set( pCC) ; + bRat0 = true ; + } + if ( ! bRat1) { + ICurveComposite* pCC( CreateCurveComposite()) ; + for ( int k = 0 ; k < nSpanU1 ; ++k) { + ICurveBezier* pCrvBez = GetCurveBezier( pCrvU1->GetCurve( k)->Clone()) ; + pCrvBez->MakeRational() ; + pCC->AddCurve( pCrvBez) ; + } + pCrvU1.Set( pCC) ; + bRat1 = true ; + } + } + + if ( nDegU0 != nDegU1) + return nullptr ; + + int nDegU = nDegU0 ; + + // in V decido che la funzione è una patch di grado 1 + int nSpanV = 1 ; + int nDegV = 1 ; + + //// se le due curve hanno lo stesso numero di span semplicemente creo la superficie // NON BASTA!! DEVO COMUNQUE TENER CONTO DELLA MODALITA' RICHIESTA + //if ( nSpanU0 == nSpanU1) { + // // inizializzo la curva e aggiungo i punti di controllo + // Init( nDegU0, nDegV, nSpanU0, nSpanV, bRat0) ; + // // scorro sul parametro V // do per scontato di avere una patch di grado 1 ( quindi nel parametro V ho solo due punti) + // for ( int j = 0 ; j < nDegV + 1 ; ++j) { + // // scorro le patch nel parametro U + // for ( int k = 0 ; k < nSpanU0 ; ++k) { + // const ICurveBezier* pSubCrvU = GetCurveBezier( j == 0 ? pCrvU0->GetCurve( k) : pCrvU1->GetCurve( k)) ; + // // scorro i punti di controllo in U + // for ( int i = 0 ; i < nDegU0 + 1 ; ++i ) { + // double dW = pSubCrvU->GetControlWeight( i) ; + // Point3d ptCtrl = pSubCrvU->GetControlPoint( i) ; + // if ( ! bRat0) + // SetControlPoint( nDegU0 * k + i, j, ptCtrl) ; + // else + // SetControlPoint( nDegU0 * k + i, j , ptCtrl, dW) ; + // } + // } + // } + //} + + + // se sto usando la ISOPARM o la MINDIST semplice allora collego più span di una curva allo stesso punto + // ( aggiungo virtualmente delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) + if ( nRuledType != RLT_B_MINDIST_PLUS){ + // ho bisogno della rappresentazione delle curve in forma di polyline, con inizio e fine delle sottocurve + PolyLine plU0, plU1 ; + int nCount0 = 0 ; + DBLVECTOR vdW0 ; + for ( int k = 0 ; k < nSpanU0 ; ++k ) { + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( k)) ; + for ( int i = 0 ; i < nDegU + 1 ; ++i ) { + Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; // il caso razionale come è da gestire????? devo usare i punti omogenei per il calcolo delle distanze?? + if ( bRat0 && ( i != 0 || i == 0 && k == 0)) + vdW0.push_back( pSubCrv0->GetControlWeight( i)) ; + // aggiungo alla polyline solo gli estremi delle sottocurve ( senza ripetizioni) + if ( ( (i == 0 && k == 0) || i == nDegU) && plU0.AddUPoint( nCount0, ptCtrl)) + ++ nCount0 ; + } + } + int nCount1 = 0 ; + DBLVECTOR vdW1 ; + for ( int k = 0 ; k < nSpanU1 ; ++k ) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( k)) ; + for ( int i = 0 ; i < nDegU1 + 1 ; ++i ) { + Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; + if ( bRat1 && ( i != 0 || i == 0 && k == 0)) + vdW1.push_back( pSubCrv1->GetControlWeight( i)) ; + if ( ( (i == 0 && k == 0) || i == nDegU1) && plU1.AddUPoint( nCount1, ptCtrl)) + ++ nCount1 ; + } + } + + // verifico ci siano almeno due punti diversi per curva + if ( ( plU0.IsClosed() && plU0.GetPointNbr() < 3) || plU0.GetPointNbr() < 2) + return false ; + if ( ( plU1.IsClosed() && plU1.GetPointNbr() < 3) || plU1.GetPointNbr() < 2) + return false ; + + + if ( nRuledType == RLT_B_MINDIST) { + // creo le liste di punti per le isoparametriche in U + PNTIVECTOR vPnt0Match, vPnt1Match ; + bool bCommonPoint = false ; + AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; + // determino il numero di span che avrà lòa superficie basandomi sulla curva con più sottocurve + int nSpanU = max( nSpanU0, nSpanU1) ; + // inizializzo la superficie + Init( nDegU, nDegV, nSpanU, nSpanV, bRat0) ; + //// comincio ad agigungere i primi punti per le due isocurve in U + //nCount0 = 0 ; // contatore dei punti aggiunti all'isoparametrica dal vettore vPnt0Match + //nCount1 = 0 ; + //Point3d ptP00 = GetCurveBezier(pCrvU0->GetCurve( 0))->GetControlPoint( 0) ; + //SetControlPoint( 0, ptP00) ; + //++ nCount0 ; + //Point3d ptP01 = GetCurveBezier(pCrvU1->GetCurve( 0))->GetControlPoint( 0) ; + //int nSecondRowInd = nDegU * nSpanU + 1 ; + //SetControlPoint( nSecondRowInd, ptP00) ; + //++ nCount1 ; + //// scorro le patch e aggiungo i relativi punti di controllo + //for ( int k = 0 ; k < nSpanU ; ++k) { + // for ( int i = 0 ; i < nDegU ; ++i) { + // if ( k == 0 && i == 0) + // continue ; + // vPnt0Match[] + // } + //} + + // mi basta scorrere il vettore vPnt1Match che mi dice che punti devo aggiungere della prima isocurva + nCount0 = 0 ; + int nIndMatch = 0 ; + int nIndMatchNext = 0 ; + int nLastPoint = nDegU + 1 ; + // scorro gli estremi delle sottocurve della curva 1 + for ( int i = 0 ; i < int( vPnt1Match.size() - 1) ; ++i) { + nIndMatch = vPnt1Match[i].second ; + nIndMatchNext = vPnt1Match[i+1].second ; + if ( nIndMatch == nSpanU0) + break ; + const ICurveBezier* pSubCrv0 ; + if ( nIndMatch == nIndMatchNext) { + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nIndMatch)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( 0)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( 0), pSubCrv0->GetControlWeight( 0)) ; + } + ++ nCount0 ; + } + else { + for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nIndMatch + k)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + } + ++ nCount0 ; + } + } + } + // controllo di aver aggiunto anche gli ultimi punti + int nInd = nIndMatchNext < nSpanU0 ? nIndMatchNext : nIndMatchNext - 1 ; + while ( nCount0 < nSpanU) { + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nInd)) ; + for ( int j = 1 ; j < nLastPoint ; ++j) { + int nPoint = nInd < nSpanU0 - 1 ? j : nDegU ; + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; + } + ++ nCount0 ; + if ( nInd < nSpanU0 - 1) + ++ nInd ; + } + nCount1 = 0 ; + int nSecondRowInd = nDegU * nSpanU + 1 ; + for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { + nIndMatch = vPnt0Match[i].second ; + nIndMatchNext = vPnt0Match[i+1].second ; + if ( nIndMatch == nSpanU1) + break ; + const ICurveBezier* pSubCrv1 ; + if ( nIndMatch == nIndMatchNext) { + pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch)) ; + for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if( ! bRat1) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0), pSubCrv1->GetControlWeight( 0)) ; + } + ++ nCount1 ; + } + else { + for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { + pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; + for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if( ! bRat1) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; + } + ++ nCount1 ; + } + } + } + // controllo di aver aggiunto anche gli ultimi punti + nInd = nIndMatchNext < nSpanU1 ? nIndMatchNext : nIndMatchNext - 1 ; + while ( nCount1 < nSpanU) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; + for ( int j = 1 ; j < nLastPoint ; ++j) { + int nPoint = nInd < nSpanU1 - 1 ? j : nDegU ; + if( ! bRat1) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint), pSubCrv1->GetControlWeight( nPoint)) ; + } + ++ nCount1 ; + if ( nInd < nSpanU1 - 1) + ++ nInd ; + } + } + + if ( nRuledType == RLT_B_ISOPAR) { + ; + } + + } + // spezzo le curve di bezier dove è necessario aggiungere dei punti + else if ( nRuledType == RLT_B_MINDIST_PLUS ) { + ; + } + + return true ; +} + diff --git a/SurfBezier.h b/SurfBezier.h index c541e39..386e1c5 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -141,6 +141,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ; bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ; + bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ; + bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ; public : // IGeoObjRW int GetNgeId( void) const override ; From 2361225321e58afedae53de7f8abc375693a4334 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 28 May 2024 16:29:10 +0200 Subject: [PATCH 15/45] EgtGeomKernel : - aggiunte le chiamate per la creazione di una rigata come superficie di Bezier - aggiunta la funzione per la creazione del cono come Bezier ( ancora da implementare). --- SbzFromCurves.cpp | 123 ++++++++++++++++++++++++++-------------------- SbzStandard.cpp | 33 +++++++++++++ 2 files changed, 104 insertions(+), 52 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 9e0bab1..ab77a4a 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -1082,55 +1082,74 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // // restituisco la superficie // return Release( pSTM) ; //} -// -////------------------------------------------------------------------------------- -//ISurfBezier* -//GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// -//{ -// // verifica parametri -// if ( &ptP == nullptr || pCurve == nullptr) -// return nullptr ; -// // calcolo la polilinea che approssima la curva -// PolyLine PL ; -// if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) -// return nullptr ; -// // creo e setto la superficie trimesh -// PtrOwner pSTM( CreateBasicSurfTriMesh()) ; -// if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptP, PL)) -// return nullptr ; -// // salvo tolleranza lineare usata -// pSTM->SetLinearTolerance( dLinTol) ; -// // restituisco la superficie -// return Release( pSTM) ; -//} -// -////------------------------------------------------------------------------------- -//ISurfBezier* -//GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// -//{ -// // verifica parametri -// if ( pCurve1 == nullptr || pCurve2 == nullptr) -// return nullptr ; -// -// // qui anziché fare le polyline converto le curve in bezier! -// // SE NON HO LO STESSO NUMERO DI CURVE COME LO GESTISCO?? -// -// // calcolo la polilinea che approssima la prima curva -// PolyLine PL1 ; -// if ( ! pCurve1->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL1)) -// return nullptr ; -// // calcolo la polilinea che approssima la seconda curva -// PolyLine PL2 ; -// if ( ! pCurve2->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL2)) -// return nullptr ; -// -// -// // creo e setto la superficie trimesh -// PtrOwner pSbz( CreateBasicSurfBezier()) ; -// if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( PL1, PL2, nType)) -// return nullptr ; -// //// salvo tolleranza lineare usata -// //pSbz->SetLinearTolerance( dLinTol) ; -// // restituisco la superficie -// return Release( pSbz) ; -//} \ No newline at end of file + +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol) +{ + // verifica parametri + if ( &ptP == nullptr || pCurve == nullptr) + return nullptr ; + //// calcolo la polilinea che approssima la curva + //PolyLine PL ; + //if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + // return nullptr ; + // creo e setto la superficie trimesh + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve)) + return nullptr ; + //// salvo tolleranza lineare usata + //pSbz->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} + +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol) +{ + // verifica parametri + if ( pCurve1 == nullptr || pCurve2 == nullptr) + return nullptr ; + + // qui anziché fare le polyline converto le curve in bezier! + // SE NON HO LO STESSO NUMERO DI CURVE COME LO GESTISCO?? + + //// calcolo la polilinea che approssima la prima curva + //PolyLine PL1 ; + //if ( ! pCurve1->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL1)) + // return nullptr ; + //// calcolo la polilinea che approssima la seconda curva + //PolyLine PL2 ; + //if ( ! pCurve2->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL2)) + // return nullptr ; + + + // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier + // se la curva è già una bezier singola la tengo, sennò la converto // e la compo di bezier??? + PtrOwner pCC1( CreateCurveComposite()) ; + if ( pCurve1->GetType() != CRV_BEZIER) + pCC1->AddCurve( CurveToBezierCurve( pCurve1)) ; + else + pCC1->AddCurve( pCurve1->Clone()) ; + if ( IsNull( pCC1) || ! pCC1->IsValid()) + return false ; + + // se la curva è già una bezier singola la tengo, sennò la converto + PtrOwner pCC2( CreateCurveComposite()) ; + if ( pCurve2->GetType() != CRV_BEZIER) + pCC2->AddCurve( CurveToBezierCurve( pCurve2)) ; + else + pCC2->AddCurve( pCurve2->Clone()) ; + if ( IsNull( pCC2) || ! pCC2->IsValid()) + return false ; + + // creo e setto la superficie trimesh + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType)) + return nullptr ; + //// salvo tolleranza lineare usata + //pSbz->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; +} \ No newline at end of file diff --git a/SbzStandard.cpp b/SbzStandard.cpp index f01903a..ea4f4b1 100644 --- a/SbzStandard.cpp +++ b/SbzStandard.cpp @@ -17,6 +17,7 @@ #include "SurfTriMesh.h" #include "SurfBezier.h" #include "/EgtDev/Include/EGkSbzStandard.h" +#include "/EgtDev/Include/EGkSbzFromCurves.h" using namespace std ; @@ -78,3 +79,35 @@ GetSurfBezierSphere( const Point3d& ptCenter, double dR) return Release( pSrfBez) ; } + +////------------------------------------------------------------------------------- +//ISurfBezier* +//GetSurfBezierCone( const Point3d& ptCenter, double dRadius, const Vector3d& dHeight) +//{ +// // le dimensioni devono essere significative +// if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL) +// return nullptr ; +// // creo la circonferenza di base +// CurveArc cArc ; +// cArc.Set( ORIG, Z_AX, dRadius) ; +// if ( dHeight < 0) +// cArc.Invert() ; +// // punto di vertice +// Point3d ptTip( 0, 0, dHeight) ; +// // creo la superficie laterale del cono +// PtrOwner pSbz( GetSurfBezierRuled( ptTip, &cArc)) ; +// if ( IsNull( pSbz)) +// return nullptr ; +// +// //// creo la superficie di base e la inverto +// //PtrOwner pSTM1( GetSurfTriMeshByFlatContour( &cArc, dLinTol)) ; +// //if ( IsNull( pSTM1)) +// // return nullptr ; +// //pSTM1->Invert() ; +// //// la unisco alla superficie del fianco +// //if ( ! pSTM->DoSewing( *pSTM1)) +// // return nullptr ; +// +// // restituisco la superficie +// return Release( pSbz) ; +//} From b854c9588b944a361affb38a1fff9f14305d740c Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 29 May 2024 17:22:09 +0200 Subject: [PATCH 16/45] =?UTF-8?q?EgtGeomKernel=20:=20-=20implementata=20la?= =?UTF-8?q?=20versione=20ruled=20Bezier=20con=20la=20modalit=C3=A0=20isopa?= =?UTF-8?q?rametrica.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 180 +++++++++++++++++++++++++++++++++++++++++-------- SurfBezier.h | 1 + 2 files changed, 153 insertions(+), 28 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 65087f1..58ac67a 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3848,40 +3848,24 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int if ( ( plU1.IsClosed() && plU1.GetPointNbr() < 3) || plU1.GetPointNbr() < 2) return false ; - + // determino il numero di span che avrà lòa superficie basandomi sulla curva con più sottocurve + int nSpanU = max( nSpanU0, nSpanU1) ; + // punti per curva + int nLastPoint = nDegU + 1 ; + // definisco la razionalità + bool bRat = bRat0 && bRat1 ; + // inizializzo la superficie + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + int nSecondRowInd = nDegU * nSpanU + 1 ; if ( nRuledType == RLT_B_MINDIST) { // creo le liste di punti per le isoparametriche in U PNTIVECTOR vPnt0Match, vPnt1Match ; bool bCommonPoint = false ; AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; - // determino il numero di span che avrà lòa superficie basandomi sulla curva con più sottocurve - int nSpanU = max( nSpanU0, nSpanU1) ; - // inizializzo la superficie - Init( nDegU, nDegV, nSpanU, nSpanV, bRat0) ; - //// comincio ad agigungere i primi punti per le due isocurve in U - //nCount0 = 0 ; // contatore dei punti aggiunti all'isoparametrica dal vettore vPnt0Match - //nCount1 = 0 ; - //Point3d ptP00 = GetCurveBezier(pCrvU0->GetCurve( 0))->GetControlPoint( 0) ; - //SetControlPoint( 0, ptP00) ; - //++ nCount0 ; - //Point3d ptP01 = GetCurveBezier(pCrvU1->GetCurve( 0))->GetControlPoint( 0) ; - //int nSecondRowInd = nDegU * nSpanU + 1 ; - //SetControlPoint( nSecondRowInd, ptP00) ; - //++ nCount1 ; - //// scorro le patch e aggiungo i relativi punti di controllo - //for ( int k = 0 ; k < nSpanU ; ++k) { - // for ( int i = 0 ; i < nDegU ; ++i) { - // if ( k == 0 && i == 0) - // continue ; - // vPnt0Match[] - // } - //} - // mi basta scorrere il vettore vPnt1Match che mi dice che punti devo aggiungere della prima isocurva nCount0 = 0 ; int nIndMatch = 0 ; int nIndMatchNext = 0 ; - int nLastPoint = nDegU + 1 ; // scorro gli estremi delle sottocurve della curva 1 for ( int i = 0 ; i < int( vPnt1Match.size() - 1) ; ++i) { nIndMatch = vPnt1Match[i].second ; @@ -3928,7 +3912,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nInd ; } nCount1 = 0 ; - int nSecondRowInd = nDegU * nSpanU + 1 ; for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { nIndMatch = vPnt0Match[i].second ; nIndMatchNext = vPnt0Match[i+1].second ; @@ -3976,11 +3959,123 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } if ( nRuledType == RLT_B_ISOPAR) { - ; + Point3d ptP0Start ; pCrvU0->GetStartPoint( ptP0Start) ; + Point3d ptP1Start ; pCrvU1->GetStartPoint( ptP1Start) ; + // setto i primi due punti delle righe + nCount0 = 0 ; // sottocurva su pCrvU0 + if ( ! bRat) + SetControlPoint( 0, ptP0Start) ; + else + SetControlPoint( 0, ptP0Start, vdW0[0]) ; + nCount1 = 0 ; // sottocurva su pCrvU1 + if ( ! bRat) + SetControlPoint( nSecondRowInd, ptP1Start) ; + else + SetControlPoint( nSecondRowInd, ptP1Start, vdW1[0]) ; + + INTVECTOR vMatch ; + int nLong = 0 ; + // prendo la polyline con più punti e scelgo a quali punti dell'altra polyline vanno associati + FindMatchByParam( plU0, plU1, vMatch,nLong) ; + + for( int i = 0 ; i < int( vMatch.size() - 1) ; ++i) { + int nCount = i ; // span in U aggiunte + // scorro i punti della polyline più lunga + // se il punto corrente e il successivo sono associati allo stesso punto dell'altra polyline + // allora devo aggiungere la sottocurva della curva più lunga e ripetere l'ultimo punto aggiunto dell'altra polyline + // se il corrente e il successivo sono associati a punti successivi + // allora devo aggiungere una sottocurva per ognuna delle due curve + if ( vMatch[i] == vMatch[i+1]) { + // se la curva più lunga è la prima + if ( nLong == 0) { + // aggiungo la curva sulla prima riga + for ( int i = 1 ; i < nLastPoint ; ++i) { + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCount0)) ; + Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; + if ( ! bRat) + SetControlPoint( nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv0->GetControlWeight( i) ; + SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; + } + } + ++ nCount0 ; + // riaggungo lo start point sulla seconda riga + // o end point se ho già aggiunto tutte le curve + int nInd = nCount1 < nSpanU1 ? 0 : nDegU ; + int nSubCrv = nCount1 < nSpanU1 ? nCount1 : nSpanU1 - 1 ; + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nSubCrv)) ; + Point3d ptCtrl = pSubCrv1->GetControlPoint( nInd) ; + for ( int i = 1 ; i < nLastPoint ; ++i) { + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv1->GetControlWeight( i) ; + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; + } + } + } + else { + // aggiungo la curva sulla seconda riga + for ( int i = 1 ; i < nLastPoint ; ++i) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCount1)) ; + Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv1->GetControlWeight( i) ; + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; + } + } + ++ nCount1 ; + // riaggungo lo start point sulla prima riga + // o end point se ho già aggiunto tutte le curve + int nInd = nCount0 < nSpanU0 ? 0 : nDegU ; + int nSubCrv = nCount0 < nSpanU0 ? nCount0 : nSpanU0 - 1 ; + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSubCrv)) ; + Point3d ptCtrl = pSubCrv0->GetControlPoint( nInd) ; + for ( int i = 1 ; i < nLastPoint ; ++i) { + if ( ! bRat) + SetControlPoint( nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv0->GetControlWeight( i) ; + SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; + } + } + } + } + // altrimenti aggiungo una sottocurva da entrambe le curve + else { + // aggiungo la curva sulla prima riga + for ( int i = 1 ; i < nLastPoint ; ++i) { + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCount0)) ; + Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; + if ( ! bRat) + SetControlPoint( nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv0->GetControlWeight( i) ; + SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; + } + } + ++ nCount0 ; + // aggiungo la curva sulla seconda riga + for ( int i = 1 ; i < nLastPoint ; ++i) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCount1)) ; + Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv1->GetControlWeight( i) ; + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; + } + } + ++ nCount1 ; + } + } } } - // spezzo le curve di bezier dove è necessario aggiungere dei punti + // spezzo le curve di bezier dove è necessario aggiungere dei punti // parametrizzo le curve sulla lunghezza else if ( nRuledType == RLT_B_MINDIST_PLUS ) { ; } @@ -3988,3 +4083,32 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int return true ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const +{ + int nPoints0 = pl0.GetPointNbr() ; + int nPoints1 = pl1.GetPointNbr() ; + DBLVECTOR vSplit ; + int nMin = min( nPoints0, nPoints1) ; + for ( int i = 0 ; i < nMin - 1 ; ++i) { + // valuto il limite dell'area di influenza dei punti della curva con meno punti + // per i punti intermedi il limite è la metà tra i punti + // per il primo e l'ultimo punto aumento il peso di quest'ultimi nel calcolo della media + if ( i == 0) + vSplit.push_back( (i * (1./3.) + ( i + 1) * ( 2./3.)) / ( nMin - 1)) ; + else if ( i == nMin - 2) + vSplit.push_back( (i * (2./3.) + ( i + 1) * ( 1./3.)) / ( nMin - 1)) ; + else + vSplit.push_back( ( 2. * i + 1) / (2 * ( nMin - 1))) ; + } + int nCount = 0 ; + int nMax = max(nPoints0, nPoints1) ; + nLong = nPoints0 < nPoints1 ? 1 : 0 ; + for ( double j = 0 ; j < nMax ; ++j) { + if ( nCount < int(vSplit.size()) && j / ( nMax - 1) > vSplit[nCount] ) + ++nCount ; + vMatch.push_back( nCount) ; + } + return true ; +} diff --git a/SurfBezier.h b/SurfBezier.h index 386e1c5..270388c 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -201,6 +201,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool UpdateEdgesFromTree( Tree& tr) const ; // funzione che calcola se gli edge sono collassati in poli bool CalcPoles( void) ; + bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto From 3b81a6b92e82d85b54314db6218802612833ce64 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 30 May 2024 16:53:37 +0200 Subject: [PATCH 17/45] EgtGeomKernel : - aggiunta la ruled bezier che aggiunge punti alla curva con meno punti ( da migliorare con la parametrizzazione sulla curva totale). --- CurveAux.cpp | 2 +- SurfBezier.cpp | 244 ++++++++++++++++++++++++++++++++++++++++--------- SurfBezier.h | 1 + 3 files changed, 202 insertions(+), 45 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index e49d057..a03ad70 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -469,7 +469,7 @@ ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2) if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( *pArc)) return nullptr ; // se l'arco era piano ed è richiesta una curva di grado 3 allora aumento una volta il grado - if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO && false) // debug + if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO) pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; // restituisco la curva return Release( pCrvBez) ; diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 58ac67a..7bb7e29 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -34,6 +34,7 @@ #include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkDistPointLine.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" @@ -3780,7 +3781,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } if ( nDegU0 != nDegU1) - return nullptr ; + return false ; int nDegU = nDegU0 ; @@ -3810,53 +3811,57 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // } //} + // ho bisogno della rappresentazione delle curve in forma di polyline, con inizio e fine delle sottocurve + PolyLine plU0, plU1 ; + int nCount0 = 0 ; + DBLVECTOR vdW0 ; + for ( int k = 0 ; k < nSpanU0 ; ++k ) { + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( k)) ; + for ( int i = 0 ; i < nDegU + 1 ; ++i ) { + if( i != nDegU && !( i == 0 && k == 0)) + continue ; + Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; // il caso razionale come è da gestire????? devo usare i punti omogenei per il calcolo delle distanze?? + if ( bRat0) + vdW0.push_back( pSubCrv0->GetControlWeight( i)) ; + // aggiungo alla polyline solo gli estremi delle sottocurve ( senza ripetizioni) + if ( plU0.AddUPoint( nCount0, ptCtrl)) + ++ nCount0 ; + } + } + int nCount1 = 0 ; + DBLVECTOR vdW1 ; + for ( int k = 0 ; k < nSpanU1 ; ++k ) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( k)) ; + for ( int i = 0 ; i < nDegU1 + 1 ; ++i ) { + if( i != nDegU && !( i == 0 && k == 0)) + continue ; + Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; + if ( bRat1) + vdW1.push_back( pSubCrv1->GetControlWeight( i)) ; + if ( plU1.AddUPoint( nCount1, ptCtrl)) + ++ nCount1 ; + } + } + + // verifico ci siano almeno due punti diversi per curva + if ( ( plU0.IsClosed() && plU0.GetPointNbr() < 3) || plU0.GetPointNbr() < 2) + return false ; + if ( ( plU1.IsClosed() && plU1.GetPointNbr() < 3) || plU1.GetPointNbr() < 2) + return false ; + + // determino il numero di span che avrà lòa superficie basandomi sulla curva con più sottocurve + int nSpanU = max( nSpanU0, nSpanU1) ; + // punti per curva + int nLastPoint = nDegU + 1 ; + // definisco la razionalità + bool bRat = bRat0 && bRat1 ; + int nSecondRowInd = nDegU * nSpanU + 1 ; // se sto usando la ISOPARM o la MINDIST semplice allora collego più span di una curva allo stesso punto // ( aggiungo virtualmente delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) if ( nRuledType != RLT_B_MINDIST_PLUS){ - // ho bisogno della rappresentazione delle curve in forma di polyline, con inizio e fine delle sottocurve - PolyLine plU0, plU1 ; - int nCount0 = 0 ; - DBLVECTOR vdW0 ; - for ( int k = 0 ; k < nSpanU0 ; ++k ) { - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( k)) ; - for ( int i = 0 ; i < nDegU + 1 ; ++i ) { - Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; // il caso razionale come è da gestire????? devo usare i punti omogenei per il calcolo delle distanze?? - if ( bRat0 && ( i != 0 || i == 0 && k == 0)) - vdW0.push_back( pSubCrv0->GetControlWeight( i)) ; - // aggiungo alla polyline solo gli estremi delle sottocurve ( senza ripetizioni) - if ( ( (i == 0 && k == 0) || i == nDegU) && plU0.AddUPoint( nCount0, ptCtrl)) - ++ nCount0 ; - } - } - int nCount1 = 0 ; - DBLVECTOR vdW1 ; - for ( int k = 0 ; k < nSpanU1 ; ++k ) { - const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( k)) ; - for ( int i = 0 ; i < nDegU1 + 1 ; ++i ) { - Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; - if ( bRat1 && ( i != 0 || i == 0 && k == 0)) - vdW1.push_back( pSubCrv1->GetControlWeight( i)) ; - if ( ( (i == 0 && k == 0) || i == nDegU1) && plU1.AddUPoint( nCount1, ptCtrl)) - ++ nCount1 ; - } - } - - // verifico ci siano almeno due punti diversi per curva - if ( ( plU0.IsClosed() && plU0.GetPointNbr() < 3) || plU0.GetPointNbr() < 2) - return false ; - if ( ( plU1.IsClosed() && plU1.GetPointNbr() < 3) || plU1.GetPointNbr() < 2) - return false ; - - // determino il numero di span che avrà lòa superficie basandomi sulla curva con più sottocurve - int nSpanU = max( nSpanU0, nSpanU1) ; - // punti per curva - int nLastPoint = nDegU + 1 ; - // definisco la razionalità - bool bRat = bRat0 && bRat1 ; // inizializzo la superficie Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; - int nSecondRowInd = nDegU * nSpanU + 1 ; if ( nRuledType == RLT_B_MINDIST) { // creo le liste di punti per le isoparametriche in U PNTIVECTOR vPnt0Match, vPnt1Match ; @@ -4076,8 +4081,99 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } // spezzo le curve di bezier dove è necessario aggiungere dei punti // parametrizzo le curve sulla lunghezza - else if ( nRuledType == RLT_B_MINDIST_PLUS ) { - ; + else if ( nRuledType == RLT_B_MINDIST_PLUS ) { // probabilmente se questo funziona bene non serve la modilità ISOPARM_SMOOTH + // scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva, che poi spezzo in quel punto + // se trovo un punto già sufficientemente vicino allora non spezzo nessuna sottocurva + + int nAtStart1 = 0 ; + int nAtEnd1 = 0 ; + Point3d ptP0 ; plU0.GetFirstPoint( ptP0) ; + while ( plU0.GetNextPoint( ptP0, true)) { + // devo salvarmi se matcho più punti con lo start o l'end della curva totale + DistPointCurve dpc( ptP0, *pCrvU1, false) ; + int nFlag = 0 ; + double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + if ( dParam < EPS_SMALL ) { + ++nAtStart1 ; + continue ; + } + else if ( dParam > nSpanU1 + EPS_SMALL ) { + ++ nAtEnd1 ; + continue ; + } + Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; // devo verificare se ho già un punto di start/end nelle vicinanze + pCrvU1->AddJoint( dParam) ; + nSpanU1 = pCrvU1->GetCurveCount() ; + // devo aggiungere un controllo in modo che i parametri trovati siano sempre crescenti + } + int nAtStart0 = 0 ; + int nAtEnd0 = 0 ; + Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; + while ( plU1.GetNextPoint( ptP1, true)) { + DistPointCurve dpc( ptP1, *pCrvU0, false) ; + int nFlag = 0 ; + double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + if ( dParam < EPS_SMALL ) { + ++nAtStart0 ; + continue ; + } + else if ( dParam > nSpanU0 - EPS_SMALL ) { + ++ nAtEnd0 ; + continue ; + } + Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; // devo verificare se ho già un punto di start/end nelle vicinanze + pCrvU0->AddJoint( dParam) ; + nSpanU0 = pCrvU0->GetCurveCount() ; + } + nSpanU = max( nSpanU0, nSpanU1) ; + + if ( (nSpanU0 > nSpanU1 && nSpanU0 != nSpanU1 + nAtStart1 + nAtEnd1) || + (nSpanU0 < nSpanU1 && nSpanU1 != nSpanU0 + nAtStart0 + nAtEnd0)) + return false ; + nSecondRowInd = nDegU * nSpanU + 1 ; + // inizializzo la superficie + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // costruisco la matrice dei punti di controllo aggiungendo i punti delle due curve appena modificate + for ( int j = 0 ; j < nSpanU ; ++j) { + //int nCrv = nAtStart0 != 0 ? j - ( nAtStart0 - 1) : j ; + int nCrv = j - nAtStart0 ; + if ( j < nAtStart0) + nCrv = 0 ; + else if ( j >= nSpanU - 1 - nAtEnd0) + nCrv = nSpanU0 -1 ; + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCrv)) ; + for( int i = j == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + int nInd = i ; + if ( j < nAtStart0) + nInd = 0 ; + //else if ( j >= nSpanU - 1 - nAtEnd0 && ((nAtStart0 != 0 ? j - ( nAtStart0 - 1) : j) != nSpanU0 - 1)) + else if ( j >= nSpanU - 1 - nAtEnd0 && j - nAtStart0 != nSpanU0 - 1) + nInd = nDegU ; + if ( ! bRat) + SetControlPoint( j * nDegU + i, pSubCrv0->GetControlPoint( nInd)) ; + else + SetControlPoint( j * nDegU + i, pSubCrv0->GetControlPoint( nInd), pSubCrv0->GetControlWeight( nInd)) ; + } + } + for ( int j = 0 ; j < nSpanU ; ++j) { + int nCrv = j - nAtStart1 ; + if ( j < nAtStart1) + nCrv = 0 ; + else if ( j >= nSpanU - 1 - nAtEnd1) + nCrv = nSpanU1 -1 ; + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv)) ; + for( int i = j == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + int nInd = i ; + if ( j < nAtStart1) + nInd = 0 ; + else if ( j >= nSpanU - 1 - nAtEnd1 && j - nAtStart1 != nSpanU1 - 1) + nInd = nDegU ; + if ( ! bRat) + SetControlPoint( nSecondRowInd + j * nDegU + i, pSubCrv1->GetControlPoint( nInd)) ; + else + SetControlPoint( nSecondRowInd + j * nDegU + i, pSubCrv1->GetControlPoint( nInd), pSubCrv1->GetControlWeight( nInd)) ; + } + } } return true ; @@ -4087,6 +4183,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bool SurfBezier::FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const { + // per la modalità isoparametrica int nPoints0 = pl0.GetPointNbr() ; int nPoints1 = pl1.GetPointNbr() ; DBLVECTOR vSplit ; @@ -4112,3 +4209,62 @@ SurfBezier::FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTO } return true ; } + +//---------------------------------------------------------------------------- +bool +SurfBezier::ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveComposite* pCurve1, DBLVECTOR& vParam0, DBLVECTOR& vParam1) const +{ + int nSpanU0 = pCurve0->GetCurveCount() ; + int nSpanU1 = pCurve1->GetCurveCount() ; + DBLVECTOR vLen0 ; + DBLVECTOR vLen1 ; + double dLenTot0 = 0 ; + double dLenTot1 = 0 ; + for( int i = 0 ; i < nSpanU0 ; ++i) { + const ICurve* pSubCrv0 = pCurve0->GetCurve( i) ; + double dLen ; pSubCrv0->GetLength( dLen) ; + dLenTot0 += dLen ; + vLen0.push_back( dLen) ; + } + for( int i = 0 ; i < nSpanU1 ; ++i) { + const ICurve* pSubCrv1 = pCurve1->GetCurve( i) ; + double dLen ; pSubCrv1->GetLength( dLen) ; + dLenTot1 += dLen ; + vLen1.push_back( dLen) ; + } + // determino il parametro di ogni curva rispetto alla lunghezza totale + for ( int i = 0 ; i < nSpanU0 ; ++i) + vParam0.push_back( vLen0[i] / dLenTot0) ; + for ( int i = 0 ; i < nSpanU1 ; ++i) + vParam1.push_back( vLen1[i] / dLenTot1) ; + + return true ; +} + +////---------------------------------------------------------------------------- +//bool +//SurfBezier::FindMatchByParam( const DBLVECTOR& vParam0, const DBLVECTOR& vParam1, INTVECTOR& vMatch0, INTVECTOR& vMatch1) const +//{ +// // per la modalità parametrata sulla lunghezza +// int nPoints0 = vParam0.size() ; +// int nPoints1 = vParam1.size() ; +// DBLVECTOR vSplit ; +// for ( int i = 0 ; i < nPoints0 - 1 ; ++i) { +// // valuto il limite dell'area di influenza dei punti della curva con meno punti +// // per i punti intermedi il limite è la metà tra i punti +// // per il primo e l'ultimo punto aumento il peso di quest'ultimi nel calcolo della media +// if ( i == 0) +// vSplit.push_back( (i * (1./3.) + ( i + 1) * ( 2./3.)) / ( nPoints0 - 1)) ; +// else if ( i == nPoints0 - 2) +// vSplit.push_back( (i * (2./3.) + ( i + 1) * ( 1./3.)) / ( nPoints0 - 1)) ; +// else +// vSplit.push_back( ( 2. * i + 1) / (2 * ( nPoints0 - 1))) ; +// } +// int nCount = 0 ; +// for ( double j = 0 ; j < nPoints1 ; ++j) { +// if ( nCount < int(vSplit.size()) && j / ( nPoints1 - 1) > vSplit[nCount] ) +// ++nCount ; +// vMatch0.push_back( nCount) ; +// } +// return true ; +//} diff --git a/SurfBezier.h b/SurfBezier.h index 270388c..9693ef3 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -202,6 +202,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzione che calcola se gli edge sono collassati in poli bool CalcPoles( void) ; bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ; + bool ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveComposite* pCurve1, DBLVECTOR& vParam0, DBLVECTOR& vParam1) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto From d7d36b670afd5d1bb14c609f50ad4d72f2dc116e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 3 Jun 2024 17:30:05 +0200 Subject: [PATCH 18/45] EgtGeomKernel : - correzione alla triangolazione di span bilineari in superfici di grado superiore all'uno. --- Tree.cpp | 73 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 51fb1a0..17183f8 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -751,24 +751,6 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ; dCurvV = Dist( ptV, ptPSrf) ; dCurvU = Dist( ptU, ptPSrf) ; - - // devo calcolare anche il twist, in caso di bordi rettilinei ( superficie di grado maggiore di 1, ma che in realtà è una bilineare) - // NON posso guardare la distanza tra il punto medio delle diagonali e il punto centrale della cella ( uLoc = 0.5, vLoc = 0.5) - // posso guardare la distanza tra le due diagonali - Point3d ptP00, ptP10, ptP11, ptP01 ; - // distanza reale tra i vertici della cella - ptP00 = m_mVert[nCToSplit][0] ; - ptP10 = m_mVert[nCToSplit][1] ; - ptP11 = m_mVert[nCToSplit][2] ; - ptP01 = m_mVert[nCToSplit][3] ; - - // da implementare!!!!! serve una valutazione più fine, sennò approssimo la superficie in modo troppo grossolano!!!! - DistLineLine dll( ptP00, ptP11, ptP10, ptP01, true, true) ; - double dDist = 0 ; dll.GetDist( dDist) ; - if ( dDist > max(dCurvU, dCurvV) ) { - // devo decidere in quale direzione splittare - // dovrei capire in quale delle due direzioni è più torta la superficie - } } // faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e // se sto ancora guardando una cella abbastanza grande @@ -809,6 +791,42 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } } + // devo calcolare anche il twist, in caso di bordi rettilinei ( superficie di grado maggiore di 1, ma che in realtà è una bilineare) + // NON posso guardare la distanza tra il punto medio delle diagonali e il punto centrale della cella ( uLoc = 0.5, vLoc = 0.5) + // posso guardare la distanza tra le due diagonali + bool bTwist = false ; + Point3d ptP00, ptP10, ptP11, ptP01 ; + // distanza reale tra i vertici della cella + ptP00 = m_mVert[nCToSplit][0] ; + ptP10 = m_mVert[nCToSplit][1] ; + ptP11 = m_mVert[nCToSplit][2] ; + ptP01 = m_mVert[nCToSplit][3] ; + + // serve una valutazione più fine, sennò approssimo la superficie in modo troppo grossolano + DistLineLine dll( ptP00, ptP11, ptP10, ptP01, true, true) ; + double dDist = 0 ; dll.GetDist( dDist) ; + if ( dDist > max(dCurvU, dCurvV) && dDist > EPS_SMALL) { + bTwist = true ; + // devo decidere in quale direzione splittare + // dovrei capire in quale delle due direzioni è più torta la superficie + Vector3d vtU0 = ptP10 - ptP00 ; + Vector3d vtU1 = ptP11 - ptP01 ; + double dAngU ; + bool bDetU = false ; + vtU0.GetRotation( vtU1, vtU0 ^ vtU1, dAngU, bDetU) ; + Vector3d vtV0 = ptP01 - ptP00 ; + Vector3d vtV1 = ptP11 - ptP10 ; + double dAngV ; + bool bDetV = false ; + // faccio la get rotation tra le coppie vettori, usando come asse il loro prodotto vettoriale per ottenere la rotazione tra i due lati + // splitto nella direzione perpendicolare alla coppia di vettori più torti tra loro. + vtV0.GetRotation( vtV1, vtV0 ^ vtV1, dAngV, bDetV) ; + if ( dAngU > dAngV) + dCurvV = dDist ; + else + dCurvU = dDist ; + } + // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza // misura approssimativa della curvatura in una direzione bool bVert ; @@ -821,12 +839,12 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) bVert = true ; } m_mTree[nCToSplit].SetSplitDirVert( bVert) ; - Point3d ptP00, ptP10, ptP11, ptP01 ; + //Point3d ptP00, ptP10, ptP11, ptP01 ; + //ptP00 = m_mVert[nCToSplit][0] ; + //ptP10 = m_mVert[nCToSplit][1] ; + //ptP11 = m_mVert[nCToSplit][2] ; + //ptP01 = m_mVert[nCToSplit][3] ; // distanza reale tra i vertici della cella - ptP00 = m_mVert[nCToSplit][0] ; - ptP10 = m_mVert[nCToSplit][1] ; - ptP11 = m_mVert[nCToSplit][2] ; - ptP01 = m_mVert[nCToSplit][3] ; double dLen0 = Dist( ptP00, ptP10) ; double dLen1 = Dist( ptP10, ptP11) ; double dLen2 = Dist( ptP01, ptP11) ; @@ -868,7 +886,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) bool bSplit = false ; // dSideMinVal potrebbe essere zero se entrambi i lati che dovrei splittare sono collassati in un punto, ma questo non vuol // dire che non dovrei eseguire lo split - if ( (dSideMinVal / 2 >= dSideMin || dSideMinVal < EPS_SMALL) && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) { + if ( ! bTwist && (dSideMinVal / 2 >= dSideMin || dSideMinVal < EPS_SMALL) && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) { CurveLine cl0010, cl0001, cl1011, cl0111 ; // V=0 cl0010.Set( ptP00, ptP10) ; @@ -938,6 +956,13 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } } } + else if ( bTwist ) { + // se la cella è twistata allora l'errore lo calcolo come nelle bilineari + //double dErr = 1. / 4. * ( ( ptP00 - ptP01) + ( ptP11 - ptP10)).Len() ; + double dErr = ( ( ptP00 - ptP01) + ( ptP11 - ptP10)).Len() / 20 ; + if ( dErr > dLinTol) + bSplit = true ; + } if ( bSplit || dSideMaxVal > dSideMax) { m_mTree[nCToSplit].SetSplitDirVert( bVert) ; From 10c5d0fffe97e63b1833428dcb24c1fa28faa7cf Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 3 Jun 2024 17:31:33 +0200 Subject: [PATCH 19/45] EgtGeomKernel : - correzione alla rigata minDist con superficie Bezier. --- SurfBezier.cpp | 227 +++++++++++++++++++++++++++++++------------------ 1 file changed, 142 insertions(+), 85 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 7bb7e29..e0bf027 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3474,7 +3474,7 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V continue ; // se la curva oltrepassa l'asse allora mi fermo, se tocca l'asse, ma resta dallo stesso lato, allora vado avanti if ( iccInfo.IciA->nPrevTy != iccInfo.IciA->nNextTy) - return nullptr ; + return false ; } } } @@ -3867,100 +3867,153 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int PNTIVECTOR vPnt0Match, vPnt1Match ; bool bCommonPoint = false ; AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; - // mi basta scorrere il vettore vPnt1Match che mi dice che punti devo aggiungere della prima isocurva - nCount0 = 0 ; + + // devo contare il numero di ripetizioni dei match nel mezzo delle curve, perché aumentano il numero di span della superficie!! + int nRep0 = 0 ; int nIndMatch = 0 ; int nIndMatchNext = 0 ; - // scorro gli estremi delle sottocurve della curva 1 - for ( int i = 0 ; i < int( vPnt1Match.size() - 1) ; ++i) { - nIndMatch = vPnt1Match[i].second ; - nIndMatchNext = vPnt1Match[i+1].second ; - if ( nIndMatch == nSpanU0) - break ; - const ICurveBezier* pSubCrv0 ; - if ( nIndMatch == nIndMatchNext) { - pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nIndMatch)) ; - for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( 0)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( 0), pSubCrv0->GetControlWeight( 0)) ; - } - ++ nCount0 ; - } - else { - for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { - pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nIndMatch + k)) ; - for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; - } - ++ nCount0 ; - } - } - } - // controllo di aver aggiunto anche gli ultimi punti - int nInd = nIndMatchNext < nSpanU0 ? nIndMatchNext : nIndMatchNext - 1 ; - while ( nCount0 < nSpanU) { - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nInd)) ; - for ( int j = 1 ; j < nLastPoint ; ++j) { - int nPoint = nInd < nSpanU0 - 1 ? j : nDegU ; - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; - } - ++ nCount0 ; - if ( nInd < nSpanU0 - 1) - ++ nInd ; - } - nCount1 = 0 ; for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { nIndMatch = vPnt0Match[i].second ; nIndMatchNext = vPnt0Match[i+1].second ; - if ( nIndMatch == nSpanU1) - break ; - const ICurveBezier* pSubCrv1 ; + if ( nIndMatch != nIndMatchNext) + nRep0 += nIndMatchNext - nIndMatch - 1; + } + // reinizializzo la superficie con il nuovo numero di span in U + nSpanU = nSpanU0 + nRep0 ; + nSecondRowInd = nDegU * nSpanU + 1 ; + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + + // come riferimento tengo i match identificati dalla curva 0 + nCount0 = 0 ; + nCount1 = 0 ; + + // scorro gli estremi delle sottocurve della curva 1 + for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { + nIndMatch = vPnt0Match[i].second ; + nIndMatchNext = vPnt0Match[i+1].second ; + const ICurveBezier* pSubCrv0 ; if ( nIndMatch == nIndMatchNext) { - pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch)) ; - for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - if( ! bRat1) - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0)) ; - else - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0), pSubCrv1->GetControlWeight( 0)) ; + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; } - ++ nCount1 ; + ++ nCount0 ; + // ripeto l'ultimo punto aggiunto alla riga 2 + //int nInd = nIndMatch == nSpanU1 ? nIndMatch - 1 : nIndMatch ; + int nInd = nIndMatch - 1 ; + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; + for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + int nPoint = nCount1 == 0 ? 0 : nDegU ; + if ( ! bRat0) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; + } + ++nCount1 ; } else { + // ripeto l'ultimo punto aggiunto per il numero di curve balzate della seconda curva - 1 + // aggiungo una sottocurva dalla prima curva + for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i != 0 ? i - 1 : i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + int nPoint = nCount0 == 0 ? 0 : nDegU ; + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; + } + ++ nCount0 ; + } + // aggiungo una sottocurva dalla prima curva + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + } + ++ nCount0 ; + + + // aggiungo tutte le sottocurve che ho balzato della seconda for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { - pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; - for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - if( ! bRat1) - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; - else - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; + pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; + for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; } ++ nCount1 ; } } } - // controllo di aver aggiunto anche gli ultimi punti - nInd = nIndMatchNext < nSpanU1 ? nIndMatchNext : nIndMatchNext - 1 ; - while ( nCount1 < nSpanU) { - const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; - for ( int j = 1 ; j < nLastPoint ; ++j) { - int nPoint = nInd < nSpanU1 - 1 ? j : nDegU ; - if( ! bRat1) - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint)) ; - else - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint), pSubCrv1->GetControlWeight( nPoint)) ; - } - ++ nCount1 ; - if ( nInd < nSpanU1 - 1) - ++ nInd ; - } + + //// // QUESTO PEZZO E' DA SISTEMARE + //// controllo di aver aggiunto anche gli ultimi punti + //int nInd = nIndMatchNext < nSpanU0 ? nIndMatchNext : nIndMatchNext - 1 ; + //while ( nCount0 < nSpanU) { + // const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nInd)) ; + // for ( int j = 1 ; j < nLastPoint ; ++j) { + // int nPoint = nInd < nSpanU0 - 1 ? j : nDegU ; + // if ( ! bRat0) + // SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + // else + // SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; + // } + // ++ nCount0 ; + // if ( nInd < nSpanU0 - 1) + // ++ nInd ; + //} + + //for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { + // nIndMatch = vPnt0Match[i].second ; + // nIndMatchNext = vPnt0Match[i+1].second ; + // if ( nIndMatch == nSpanU1) + // break ; + // const ICurveBezier* pSubCrv1 ; + // if ( nIndMatch == nIndMatchNext) { + // pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch)) ; + // for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + // if( ! bRat1) + // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0)) ; + // else + // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0), pSubCrv1->GetControlWeight( 0)) ; + // } + // ++ nCount1 ; + // } + // else { + // for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { + // pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; + // for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + // if( ! bRat1) + // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; + // else + // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; + // } + // ++ nCount1 ; + // } + // } + //} + //// controllo di aver aggiunto anche gli ultimi punti + //nInd = nIndMatchNext < nSpanU1 ? nIndMatchNext : nIndMatchNext - 1 ; + //while ( nCount1 < nSpanU) { + // const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; + // for ( int j = 1 ; j < nLastPoint ; ++j) { + // int nPoint = nInd < nSpanU1 - 1 ? j : nDegU ; + // if( ! bRat1) + // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint)) ; + // else + // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint), pSubCrv1->GetControlWeight( nPoint)) ; + // } + // ++ nCount1 ; + // if ( nInd < nSpanU1 - 1) + // ++ nInd ; + //} } if ( nRuledType == RLT_B_ISOPAR) { @@ -4080,10 +4133,10 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } - // spezzo le curve di bezier dove è necessario aggiungere dei punti // parametrizzo le curve sulla lunghezza + // spezzo le curve di bezier dove è necessario aggiungere dei punti else if ( nRuledType == RLT_B_MINDIST_PLUS ) { // probabilmente se questo funziona bene non serve la modilità ISOPARM_SMOOTH - // scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva, che poi spezzo in quel punto - // se trovo un punto già sufficientemente vicino allora non spezzo nessuna sottocurva + // scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva + // in quel punto la curva verrà spezzata, a meno che non si trovi una joint già sufficientemente vicina int nAtStart1 = 0 ; int nAtEnd1 = 0 ; @@ -4127,6 +4180,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } nSpanU = max( nSpanU0, nSpanU1) ; + // se la differenza tra il numero di span delle due curve non è colmata dalla ripetizione dello start o dello'end allora devo tenere conto anche + // delle addJoint che non hanno fatto nulla ( perché chieste di splittare la curva troppo vicino ad un punto già esistente di split, magari in un caso anche di multimatch per lo stesso punto) if ( (nSpanU0 > nSpanU1 && nSpanU0 != nSpanU1 + nAtStart1 + nAtEnd1) || (nSpanU0 < nSpanU1 && nSpanU1 != nSpanU0 + nAtStart0 + nAtEnd0)) return false ; @@ -4192,10 +4247,12 @@ SurfBezier::FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTO // valuto il limite dell'area di influenza dei punti della curva con meno punti // per i punti intermedi il limite è la metà tra i punti // per il primo e l'ultimo punto aumento il peso di quest'ultimi nel calcolo della media + double dW = 2./3. ; + //double dW = 1./2. ; if ( i == 0) - vSplit.push_back( (i * (1./3.) + ( i + 1) * ( 2./3.)) / ( nMin - 1)) ; + vSplit.push_back( (i * (1- dW) + ( i + 1) * dW) / ( nMin - 1)) ; else if ( i == nMin - 2) - vSplit.push_back( (i * (2./3.) + ( i + 1) * ( 1./3.)) / ( nMin - 1)) ; + vSplit.push_back( (i * dW + ( i + 1) * ( 1 - dW)) / ( nMin - 1)) ; else vSplit.push_back( ( 2. * i + 1) / (2 * ( nMin - 1))) ; } From 980a1f62df6584d9cde5116efdcb490f763829d3 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 3 Jun 2024 17:32:14 +0200 Subject: [PATCH 20/45] EgtGeomKernel : - correzione alla gestione di curve nurbs periodiche da convertire in bezier. --- CurveAux.cpp | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index a03ad70..87ddf39 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -871,7 +871,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) } // se effettivamente ho dei nodi in più da togliere allora li tolgo if ( int( cnData.vU.size()) != int(cnData.vCP.size()) + cnData.nDeg - 1) { - // devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo sono alla fine del vettore dei nodi + // devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo siano alla fine del vettore dei nodi cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ; // controllo eventualmente anche i nodi extra // se ne ho due in più ne tolgo uno in cima e uno in fondo @@ -904,8 +904,16 @@ NurbsCurveCanonicalize( CNurbsData& cnData) cnData.vU = vU ; // verifico se ho nodi extra // se ne ho due in più ne tolgo uno in cima e uno in fondo - if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere - cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; + if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { + // significa che ci sono due nodi extra: + // se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli + if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) { + cnData.vU = vector( cnData.vU.begin() + 2, cnData.vU.end()) ; + } + // sennò ne tolgo uno all'inizio e uno alla fine + else + cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; + } // se ne ho solo uno in più lo tolgo in cima else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; @@ -944,9 +952,20 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità int b = nU - nDeg - 1 + 1 ; int i = b ; + int c = b ; while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO) -- b ; int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg + + //while ( i > 0 && abs( cnData.vU[i] - cnData.vU[i - 1]) < EPS_ZERO) + // -- i ; + //int mult = min( b - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg + + //// devo controllare anche i nodi successivi! + //while ( c < nU - 1 && abs( cnData.vU[c + 1] - cnData.vU[c]) < EPS_ZERO) + // ++ c ; + //int mult = min( c - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg + // recupero i punti da modificare if ( ! cnData.bRat) { for ( int i = 0 ; i <= nDeg - mult ; ++ i) @@ -1008,9 +1027,20 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // aumento la molteplicità del punto u_p-1 b = nDeg - 1 ; i = b ; + c = b ; while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO) -- b ; mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg + + //while ( i > 0 && abs( cnData.vU[i] - cnData.vU[i - 1]) < EPS_ZERO) + // -- i ; + //mult = min( b - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg + + //// devo controllare anche i nodi successivi! + //while ( c < nU -1 && abs(cnData.vU[c + 1] - cnData.vU[c]) < EPS_ZERO ) + // ++ c ; + //mult = min( c - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg + // recupero i punti da modificare if ( ! cnData.bRat) { for ( int i = 0 ; i <= nDeg - mult ; ++ i) @@ -1177,6 +1207,7 @@ NurbsToBezierCurve( const CNurbsData& cnData) int a = cnData.nDeg - 1 ; int b = cnData.nDeg ; bool bPrevRejected = false ; + //algoritmo A5.6 di Piegl e Tiller // ciclo while ( b < nU - 1) { int i = b ; From 261e9ac0c8f7daf29477a4a2504cd0921fa39ba5 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 5 Jun 2024 09:10:22 +0200 Subject: [PATCH 21/45] EgtGeomKernel : - correzioni alla conversione da nurbs a bezier per curve e superfici. --- CurveAux.cpp | 14 ++++++++++---- SurfAux.cpp | 29 +++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 2f0329a..f7ce65e 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -861,14 +861,14 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva // wrap della curva su se stessa if ( cnData.bPeriodic ) { - bool bRepetead = true ; + bool bRepeated = true ; for ( int i = 0 ; i < cnData.nDeg ; ++i) { if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) { - bRepetead = false ; + bRepeated = false ; break ; } } - if ( ! bRepetead){ + if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){ // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped DBLVECTOR vU = cnData.vU ; // se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo @@ -1111,15 +1111,21 @@ NurbsCurveCanonicalize( CNurbsData& cnData) nU = nU - 2 * ( nDeg - 1); PNTVECTOR vCP_clamped ; vCP_clamped.resize( nCP) ; + DBLVECTOR vW_clamped ; + vW_clamped.resize( nCP) ; DBLVECTOR vU_clamped ; vU_clamped.resize( nU) ; for ( int i = 0 ; i < nCP ; ++i) { if ( ! cnData.bRat) vCP_clamped[i] = cnData.vCP[i + nDeg - 1] ; - else + else { + vW_clamped[i] = cnData.vW[i + nDeg - 1] ; vCP_clamped[i] = cnData.vCP[i + nDeg - 1] / cnData.vW[i + nDeg - 1] ; + } } cnData.vCP = vCP_clamped ; + cnData.vW = vW_clamped ; + for ( int i = 0 ; i < nU ; ++i) { vU_clamped[i] = cnData.vU[i + nDeg - 1] ; } diff --git a/SurfAux.cpp b/SurfAux.cpp index 4e9e612..bcdd829 100644 --- a/SurfAux.cpp +++ b/SurfAux.cpp @@ -45,6 +45,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) for( int j = 0 ; j < snData.nCPV ; ++j) { CNurbsData nuCurve ; nuCurve.bPeriodic = true ; + nuCurve.bRat = snData.bRat ; nuCurve.nDeg = snData.nDegU ; nuCurve.vU = vU ; // vettore dei punti di controllo @@ -63,13 +64,23 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) nuCurve.vW = vWeCtrl ; // i punti dell' oggetto nuCurve devono essere in forma non omogenea if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie + if ( snData.mCP.size() != nuCurve.vCP.size() ) { + snData.mCP.resize( nuCurve.vCP.size()) ; + if( snData.bRat) + snData.mW.resize( nuCurve.vW.size()) ; + } for ( int i = 0 ; i < snData.nCPU ; ++i) { snData.mCP[i][j] = nuCurve.vCP[i] ; + if( snData.bRat) { + snData.mW[i][j] = nuCurve.vW[i] ; + snData.mCP[i][j] *= nuCurve.vW[i] ; + } } snData.vU = nuCurve.vU ; } } snData.bPeriodicU = false ; + snData.nCPU = int( snData.mCP.size()) ; } if ( snData.bPeriodicV || ! snData.bClampedV) { bool bIsRational = snData.bRat ; @@ -83,6 +94,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) for( int i = 0 ; i < snData.nCPU ; ++i) { CNurbsData nuCurve ; nuCurve.bPeriodic = true ; + nuCurve.bRat = snData.bRat ; nuCurve.nDeg = snData.nDegV ; nuCurve.vU = vV ; // vettore dei punti di controllo @@ -101,15 +113,28 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) nuCurve.vW = vWeCtrl ; // i punti dell' oggetto nuCurve devono essere in forma non omogenea if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie - for ( int j = 0 ; j < snData.nCPV ; ++j ) { + if ( snData.mCP[i].size() != nuCurve.vCP.size()){ + snData.mCP[i].clear() ; + snData.mCP[i].resize( nuCurve.vCP.size()) ; + if ( snData.bRat ) { + snData.mW[i].clear() ; + snData.mW[i].resize( nuCurve.vW.size()) ; + } + } + for ( int j = 0 ; j < int( nuCurve.vCP.size()) ; ++j ) { snData.mCP[i][j] = nuCurve.vCP[j] ; + if ( snData.bRat ) { + snData.mW[i][j] = nuCurve.vW[j] ; + snData.mCP[i][j] *= nuCurve.vW[j] ; + } } snData.vV = nuCurve.vU ; } } snData.bPeriodicV = false ; + snData.nCPV = int( snData.mCP[0].size()) ; } - return true; + return true ; } //---------------------------------------------------------------------------- From f67865f9cc4ff467e63c3920daf3b3df5c513073 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 6 Jun 2024 09:12:47 +0200 Subject: [PATCH 22/45] EgtGeomKernel : - piccola correzione di una tolleranza. --- DistPointSurfTm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DistPointSurfTm.cpp b/DistPointSurfTm.cpp index db2df80..e3b049c 100644 --- a/DistPointSurfTm.cpp +++ b/DistPointSurfTm.cpp @@ -152,7 +152,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) double dCurSqDist ; // Se la distanza del triangolo è valida e minore di quella attuale aggiorno if ( distPT.GetSqDist( dCurSqDist)) { - if ( abs( dCurSqDist - dMinSqDist) < EPS_SMALL) // se distanze uguali... + if ( abs( dCurSqDist - dMinSqDist) < SQ_EPS_SMALL) // se distanze uguali... vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo else if ( dCurSqDist < dMinSqDist) { // se minore... vTria.clear() ; // pulisco il vettore From b34d31029becc6d78cd4677663064ae0a1d6141f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 6 Jun 2024 09:13:57 +0200 Subject: [PATCH 23/45] EgtGeomKernel : - piccola correzione. --- SbzFromCurves.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index ab77a4a..2185f08 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -1133,7 +1133,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou else pCC1->AddCurve( pCurve1->Clone()) ; if ( IsNull( pCC1) || ! pCC1->IsValid()) - return false ; + return nullptr ; // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC2( CreateCurveComposite()) ; @@ -1142,7 +1142,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou else pCC2->AddCurve( pCurve2->Clone()) ; if ( IsNull( pCC2) || ! pCC2->IsValid()) - return false ; + return nullptr ; // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; From e32b85bc2da00f02630c9d187def1fd4624073c7 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 7 Jun 2024 16:00:24 +0200 Subject: [PATCH 24/45] EgtGeomKernel : - correzione alla triangolazione di sup. di Bezier con patch con lati collassati in un polo. --- Tree.cpp | 24 +++++++++++++++--------- Tree.h | 16 ++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 17183f8..5b4be0f 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1712,12 +1712,15 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) } // se non l'ho già aggiunto tramite i vicini bottom aggiungo il punto bottom right - else if ( ! bBottomRight) { + // controllo anche che ptBL e ptBr non coincidano ( nel 3D). Altrimenti vuol dire che quel lato della cella è su un lato di polo e basta aggiungere un punto solo + else if ( ! bBottomRight && ! AreSamePointApprox( m_mVert.at(nId).at(0), m_mVert.at(nId).at(1)) ) { Point3d ptBr( m_mTree.at( nId).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; vVertices.push_back( ptBr) ; } vNeigh.clear() ; - vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; + // se il lato destro della cella non sta su un lato di polo ( ptTR != ptBr nel 3D) allora aggiungo anche ptTR + if( ! AreSamePointApprox( m_mVert.at(nId).at(1), m_mVert.at(nId).at(2))) + vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; GetTopNeigh ( nId, vNeigh) ; std::reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top @@ -1757,12 +1760,15 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) } } // se non l'ho già aggiunto tramite i vicini top aggiungo il punto top left - else if ( ! bTopLeft) { + // controllo anche che ptTl e ptTR non coincidano ( nel 3D). Altrimenti vuol dire che quel lato della cella è su un lato di polo e basta aggiungere un punto solo + else if ( ! bTopLeft && ! AreSamePointApprox( m_mVert.at(nId).at(2), m_mVert.at(nId).at(3))) { Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; vVertices.push_back( ptTl) ; } vNeigh.clear() ; - vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + // se il lato sinistro della cella non sta su un lato di polo ( ptTR != ptBr nel 3D) allora aggiungo anche ptTR + if( ! AreSamePointApprox( m_mVert.at(nId).at(3), m_mVert.at(nId).at(0))) + vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; if ( ! m_bTrimmed) { // se ho una cella con vicino dello stesso grado ( quindi il poligono ha solo 5 punti) controllo la curvatura nella cella e // se necessario cambio l'ordine dei vertici per scegliere la diagonale di split migliore @@ -1932,23 +1938,23 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells // potrei essere su un lato if ( nEdge == 0 || nEdge == 1 || nEdge == 2 || nEdge == 3) { // se è orientato con il lato mi sposto a destra - if ( ( nEdge == 0 || nEdge == 2 ) && abs(vtDir.x) > 1 - EPS_SMALL ) { + if ( ( nEdge == 0 || nEdge == 2 ) && abs(vtDir.x) > 1 - EPS_SMALL/100 ) { Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -90) ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; } - else if ( (nEdge == 0 || nEdge == 2) && abs(vtDir.y) > EPS_SMALL) + else if ( (nEdge == 0 || nEdge == 2) && abs(vtDir.y) > EPS_SMALL/100) ptIntersPlus.y += (vtDir.y > 0 ? 1 : -1) * EPS_SMALL ; - else if ( ( nEdge == 1 || nEdge == 3 ) && abs(vtDir.y) > 1 - EPS_SMALL ) { + else if ( ( nEdge == 1 || nEdge == 3 ) && abs(vtDir.y) > 1 - EPS_SMALL/100 ) { Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -90) ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; } - else if ( (nEdge == 1 || nEdge == 3) && abs(vtDir.x) > EPS_SMALL) + else if ( (nEdge == 1 || nEdge == 3) && abs(vtDir.x) > EPS_SMALL/100) ptIntersPlus.x += (vtDir.x > 0 ? 1 : -1) * EPS_SMALL ; } // o in un vertice else if ( nEdge == 4 || nEdge == 5 || nEdge == 6 || nEdge == 7) { // se non è orientato con gli assi procedo con la direzione del trim - if ( abs(vtDir.x) < 1 - EPS_SMALL && abs(vtDir.y) < 1 - EPS_SMALL ) + if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 ) ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ; // altrimenti ruoto a destra else { diff --git a/Tree.h b/Tree.h index 39a6cd1..da3042a 100644 --- a/Tree.h +++ b/Tree.h @@ -185,9 +185,9 @@ class Cell { return Point3d( m_ptPtr.x, m_ptPbl.y); } double GetSplitValue( void) const { return m_dSplit ; } - bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, senn� orizzontalmente + bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente { return m_bSplitVert ; } - bool IsLeaf( void) const // flag che indica se la cella ha figli o se � una foglia + bool IsLeaf( void) const // flag che indica se la cella ha figli o se è una foglia { return ( m_nChild1 == -2 && m_nChild2 == -2) ; } bool IsProcessed( void) const // flag che indica se tutti i figli della cella, se ce ne sono, sono stati processati { return m_bProcessed ; } @@ -235,8 +235,8 @@ class Tree Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno bool SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini) - bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax � il massimo per la dimensione maggiore di un triangolo della trimesh - // dSideMin � lunghezza minima del lato di una cella nello spazio reale + bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh + // dSideMin è lunghezza minima del lato di una cella nello spazio reale bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; bool GetPolygons( POLYLINEMATRIX& vPolygons) ; bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero @@ -256,8 +256,8 @@ class Tree private : bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert - bool Split( int nId) ; // funzione di split di una cella dell'albero a met� nella direzione data da bVert - void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondit� di +- 1 + bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert + void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondità di +- 1 int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId int GetDepth( int nId, int nRef) const ; // livello del nodo nId void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top @@ -310,8 +310,8 @@ class Tree int m_nSpanU ; // numero di span lungo il parametro U int m_nSpanV ; // numero di span lungo il parametro V POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree - std::map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 � puntatore Null e -1 � root - std::map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id � lo stesso che la cella ha in m_mTree + std::map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root + std::map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01 INTVECTOR m_vnLeaves ; // vettore delle foglie INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch bool m_bTestMode ; // bool che indica se la test mode è attiva From e2008bd479c3de739aa0794659a3c2e966e89823 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 7 Jun 2024 17:41:39 +0200 Subject: [PATCH 25/45] EgtGeomKernel : - correzione ulteriore alla triangolazione delle superfici bezier con patch con lati collassati. --- Tree.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 5b4be0f..f005dbe 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1674,6 +1674,10 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) vVertices.clear() ; vNeigh.clear() ; vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + INTVECTOR vnVert ; + BOOLVECTOR vbBonusVert(4) ; + fill( vbBonusVert.begin(), vbBonusVert.end(), false) ; + vnVert.push_back( int(vVertices.size()) - 1) ; GetBottomNeigh( nId, vNeigh) ; // aggiungo i vertici che sono sul lato bottom, solo se ho più di un vicino bottom if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){ @@ -1690,6 +1694,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) vVertices.push_back( m_mTree.at( j).GetTopRight()) ; } bBottomRight = true ; + vbBonusVert[2] = true ; } else bBottomRight = false ; @@ -1699,6 +1704,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){ // se la superficie è chiusa lungo il parametro U e le celle vicine right sono sul lato Left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. + vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedU && m_mTree.at( vNeigh[0]).m_bOnLeftEdge ) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; @@ -1709,24 +1715,24 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) for ( int j : vNeigh) vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ; } - + vbBonusVert[3] = true ; } // se non l'ho già aggiunto tramite i vicini bottom aggiungo il punto bottom right - // controllo anche che ptBL e ptBr non coincidano ( nel 3D). Altrimenti vuol dire che quel lato della cella è su un lato di polo e basta aggiungere un punto solo - else if ( ! bBottomRight && ! AreSamePointApprox( m_mVert.at(nId).at(0), m_mVert.at(nId).at(1)) ) { + else if ( ! bBottomRight) { Point3d ptBr( m_mTree.at( nId).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; vVertices.push_back( ptBr) ; + vnVert.push_back( int(vVertices.size()) - 1) ; } vNeigh.clear() ; - // se il lato destro della cella non sta su un lato di polo ( ptTR != ptBr nel 3D) allora aggiungo anche ptTR - if( ! AreSamePointApprox( m_mVert.at(nId).at(1), m_mVert.at(nId).at(2))) - vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; + vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; + vnVert.push_back( int(vVertices.size()) - 1) ; GetTopNeigh ( nId, vNeigh) ; std::reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top if ( ! vNeigh.empty() && vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro V e la cella è sul lato top // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. + vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedV && m_mTree.at( nId).m_bOnTopEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; @@ -1738,6 +1744,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ; } bTopLeft = true ; + vbBonusVert[0] = true ; } else bTopLeft = false ; @@ -1748,6 +1755,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro U e la cella è sul lato left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. + vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedU && m_mTree.at( nId).m_bOnLeftEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; @@ -1758,17 +1766,68 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) for ( int j : vNeigh) vVertices.push_back( m_mTree.at( j).GetTopRight()) ; } + vbBonusVert[1] = true ; } // se non l'ho già aggiunto tramite i vicini top aggiungo il punto top left - // controllo anche che ptTl e ptTR non coincidano ( nel 3D). Altrimenti vuol dire che quel lato della cella è su un lato di polo e basta aggiungere un punto solo - else if ( ! bTopLeft && ! AreSamePointApprox( m_mVert.at(nId).at(2), m_mVert.at(nId).at(3))) { + else if ( ! bTopLeft) { Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; vVertices.push_back( ptTl) ; + vnVert.push_back( int(vVertices.size()) - 1) ; } vNeigh.clear() ; - // se il lato sinistro della cella non sta su un lato di polo ( ptTR != ptBr nel 3D) allora aggiungo anche ptTR - if( ! AreSamePointApprox( m_mVert.at(nId).at(3), m_mVert.at(nId).at(0))) - vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + vnVert.push_back( int(vVertices.size()) - 1) ; + + // ora devo controllare se uno dei lati della cella è collassato in un punto. + // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra + // se ne ho messi solo su uno dei due allora devo togliere il vertice dell'altro lato + if ( AreSamePointApprox(m_mVert.at(nId).at(0), m_mVert.at(nId).at(1)) && ( vbBonusVert[1] || vbBonusVert[3])) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if( ! ( vbBonusVert[1] && vbBonusVert[3])){ + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if( vbBonusVert[1]) // lati contati a partire da quello sopra in senso CCW + vVertices.erase( vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + else if ( vbBonusVert[3]) { + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVertices.pop_back() ; + vVertices[0] = vVertices.end()[-1] ; + } + } + } + if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2)) && ( vbBonusVert[0] || vbBonusVert[2])) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if( ! ( vbBonusVert[0] && vbBonusVert[2])){ + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if( vbBonusVert[0]) // lati contati a partire da quello sopra in senso CCW + vVertices.erase( vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + else if ( vbBonusVert[2]) + vVertices.erase( vVertices.begin() + vnVert[2]) ; + } + } + if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3)) && ( vbBonusVert[1] || vbBonusVert[3])) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if( ! ( vbBonusVert[1] && vbBonusVert[3])){ + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if( vbBonusVert[1]) // lati contati a partire da quello sopra in senso CCW + vVertices.erase( vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW + else if ( vbBonusVert[3]) + vVertices.erase( vVertices.begin() + vnVert[3]) ; + } + } + if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0)) && ( vbBonusVert[0] || vbBonusVert[2])) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if( ! ( vbBonusVert[0] && vbBonusVert[2])){ + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if( vbBonusVert[0]){ // lati contati a partire da quello sopra in senso CCW + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVertices.pop_back() ; + vVertices[0] = vVertices.end()[-1] ; + } + else if ( vbBonusVert[2]) + vVertices.erase( vVertices.begin() + vnVert[3]) ; + } + } + if ( ! m_bTrimmed) { // se ho una cella con vicino dello stesso grado ( quindi il poligono ha solo 5 punti) controllo la curvatura nella cella e // se necessario cambio l'ordine dei vertici per scegliere la diagonale di split migliore From 36657e17c4779f0f21864e3d79b27b11c949001a Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 7 Jun 2024 17:42:19 +0200 Subject: [PATCH 26/45] EgtGeomKernel : - correzione alla funzione per tagliare una sup di bezier con un piano. --- SurfBezier.cpp | 192 ++++++++++++++++++++++++------------------------- 1 file changed, 95 insertions(+), 97 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 2028569..d08a966 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -65,7 +65,7 @@ SurfBezier::~SurfBezier( void) bool SurfBezier::Init( int nDegU, int nDegV, int nSpanU, int nSpanV, bool bIsRational) { - // verifico validit� grado + // verifico validità grado if ( nDegU < 1 || nDegU > MAXDEG || nDegV < 1 || nDegV > MAXDEG || nSpanU < 1 || nSpanV < 1) return false ; @@ -97,7 +97,7 @@ SurfBezier::Init( int nDegU, int nDegV, int nSpanU, int nSpanV, bool bIsRational bool SurfBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) { - // verifico validit� indice + // verifico validità indice if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd >= GetDim()) return false ; @@ -119,7 +119,7 @@ SurfBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) bool SurfBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) { - // verifico validit�, razionalit� e indice + // verifico validità, razionalità e indice if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd >= GetDim()) return false ; @@ -200,7 +200,7 @@ SurfBezier::GetTrimRegion( void) const bool SurfBezier::GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const { - // verifico validit� superficie + // verifico validità superficie if ( m_nStatus != OK) return false ; // restituisco gradi e flag di razionale @@ -217,7 +217,7 @@ SurfBezier::GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIs const Point3d& SurfBezier::GetControlPoint( int nInd, bool* pbOk) const { - // verifico validit� e indice + // verifico validità e indice if ( m_nStatus != OK || nInd < 0 || nInd >= GetDim()) { if ( pbOk != NULL) *pbOk = false ; @@ -233,7 +233,7 @@ SurfBezier::GetControlPoint( int nInd, bool* pbOk) const double SurfBezier::GetControlWeight( int nInd, bool* pbOk) const { - // verifico validit�, razionalit� e indice + // verifico validità, razionalità e indice if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd >= GetDim()) { if ( pbOk != NULL) *pbOk = false ; @@ -545,7 +545,7 @@ SurfBezier::GetPointNrmD1D2( double dU, double dV, Side nUs, Side nVs, if ( vtN.Normalize()) return true ; - // se solo una delle due derivate � piccola, mi sposto lungo il relativo parametro e uso le tangenti + // se solo una delle due derivate è piccola, mi sposto lungo il relativo parametro e uso le tangenti if ( pvtDerU->Len() < EPS_SMALL && pvtDerV->Len() > 10 * EPS_SMALL) { double dCoeff = ( dU - 1000 * EPS_PARAM < 0. ? 1 : -1) ; double dUm = dU + 1000 * EPS_PARAM * dCoeff ; @@ -652,7 +652,7 @@ SurfBezier::GetTitle( void) const bool SurfBezier::Dump( string& sOut, bool bMM, const char* szNewLine) const { - // verifico validit� superficie + // verifico validità superficie if ( m_nStatus != OK) sOut += string( "Status=Invalid") + szNewLine ; // area @@ -885,7 +885,7 @@ SurfBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, d // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validit� dell'asse di rotazione + // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -941,7 +941,7 @@ SurfBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validit� del piano di specchiatura + // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -964,7 +964,7 @@ SurfBezier::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validit� dei parametri + // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -986,11 +986,11 @@ SurfBezier::ToGlob( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validit� del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se frame identit�, non devo fare alcunch� + // se frame identità, non devo fare alcunché if ( IsGlobFrame( frRef)) return true ; @@ -1012,11 +1012,11 @@ SurfBezier::ToLoc( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validit� del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se frame identit�, non devo fare alcunch� + // se frame identità, non devo fare alcunché if ( IsGlobFrame( frRef)) return true ; @@ -1038,11 +1038,11 @@ SurfBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validit� dei frame + // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; - // se i due riferimenti coincidono, non devo fare alcunch� + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; @@ -1305,7 +1305,7 @@ SurfBezier::GetLoop( int nLoop) const // se loop chiuso lo restituisco, altrimenti errore return ( pLoop->IsClosed() ? Release( pLoop) : nullptr) ; } - // la superficie � trimmata, quindi devo cercare nei vari chunck il loop corrispondente + // la superficie è trimmata, quindi devo cercare nei vari chunck il loop corrispondente else { if ( nLoop > m_pTrimReg->GetChunkCount()) return nullptr ; @@ -1570,6 +1570,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const return nullptr ; // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d + int c = 0 ; for ( POLYLINEVECTOR vPL : vvPL) { PNTVECTOR vPnt ; INTVECTOR vTria ; @@ -1593,6 +1594,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const vPnt[vTria[3*i+2]].x, vPnt[vTria[3*i+2]].y)) return nullptr ; } + ++c ; } // termino @@ -1752,6 +1754,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& Point3d pt3DPrev = pt3D ; Point3d pt2DPrev = pt2D ; bool bPrevIsPole = false ; + bool bHorizontalPole = true ; if ( bThroughEdge) { // devo cambiare le coordinate di pt2DPrev per periodicità // capisco su quale lato è e lo porto sul lato opposto @@ -1768,21 +1771,29 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& else if ( (m_nSpanV * SBZ_TREG_COEFF - pt2DPrev.y) < 1) pt2DPrev.y = 0 ; } - bPrevIsPole = AreSamePointApprox( pt, pt2DPrev) ; + // verifico se il punto era in un polo + if ( ( m_vbPole[0] && m_nSpanV * SBZ_TREG_COEFF - pt2DPrev.y < 1 ) || + ( m_vbPole[2] && pt2DPrev.y < 1 ) ) { + bPrevIsPole = true ; + bHorizontalPole = true ; + } + if ( ( m_vbPole[1] && pt2DPrev.x < 1 ) || + ( m_vbPole[3] && m_nSpanU * SBZ_TREG_COEFF - pt2DPrev.x < 1 ) ) { + bPrevIsPole = true ; + bHorizontalPole = false ; + } } pCrv->GetEndPoint( pt3D) ; if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev, &bThroughEdge, pPlCut)) return false ; - if ( bPrevIsPole) { + + // se il precedente era passato attraverso l'edge ed era un edge di polo allora devo sistemare le coordinate + if( bPrevIsPole){ // se il punto precedente era di polo allora devo correggere le sue coordinate 2D - if ( ( m_vbPole[0] || m_vbPole[2] )) { - if ( pt2DPrev.y < 1 || m_nSpanV * SBZ_TREG_COEFF - pt2DPrev.y < 1) - pt2DPrev.x = pt2D.x ; - } - if ( ( m_vbPole[1] || m_vbPole[3] )) { - if ( pt2DPrev.x < 1 || m_nSpanU * SBZ_TREG_COEFF - pt2DPrev.x < 1) - pt2DPrev.y = pt2D.y ; - } + if ( bHorizontalPole) + pt2DPrev.x = pt2D.x ; + else if ( ! bHorizontalPole) + pt2DPrev.y = pt2D.y ; } Vector3d vtDir = pt2D - pt2DPrev ; vtDir.Normalize() ; @@ -2138,6 +2149,8 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim + // N.B. : questa funzione non prevede poli interni alla superficie, ma solo lati che sono collassati in poli!!!! + // se necessario calcolo i poli if ( m_vbPole.empty()) CalcPoles() ; @@ -2328,6 +2341,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // devo subito capire se sono in un polo o no // se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto bool bIsPole = false ; + bool bNearPole = false ; // devo capire se il triangolo di riferimento ha un vertice in un polo int nInters = 0 ; INTVECTOR vInters(4) ; fill( vInters.begin(), vInters.end(), 0) ; @@ -2381,6 +2395,39 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in pSurfTm->GetVertex( nVert[0], vPT[0]) ; pSurfTm->GetVertex( nVert[1], vPT[1]) ; pSurfTm->GetVertex( nVert[2], vPT[2]) ; + // devo capire se il trinagolo ha un vertice su un polo + int nVertOnPole = -1 ; + int nEdge = -1 ; + // do per scontato che al più un vertice possa essere in un polo + if ( m_vbPole[0] || m_vbPole[2]) { + for( int p = 0 ; p < 3 ; ++p) { + if ( ( m_vbPole[0] && vPtPa[p].y > m_nSpanV * SBZ_TREG_COEFF - EPS_SMALL ) ) { + bNearPole = true ; + nVertOnPole = p ; + nEdge = 0 ; + } + else if ( m_vbPole[2] && vPtPa[p].y < 0 + EPS_SMALL) { + bNearPole = true ; + nVertOnPole = p ; + nEdge = 2 ; + } + } + } + else if ( m_vbPole[1] || m_vbPole[3]) { + for( int p = 0 ; p < 3 ; ++p) { + if ( ( m_vbPole[3] && vPtPa[p].x > m_nSpanU * SBZ_TREG_COEFF - EPS_SMALL)) { + bNearPole = true ; + nVertOnPole = p ; + nEdge = 3 ; + } + else if ( m_vbPole[1] && vPtPa[p].x < 0 + EPS_SMALL) { + bNearPole = true ; + nVertOnPole = p ; + nEdge = 1 ; + } + } + } + // se la superficie è chiusa controllo se devo tenere conto della periodicità nel prendere le coordinate parametriche dei vertici double dParamH, dParamL ; if ( m_bClosedU || m_bClosedV) { @@ -2404,11 +2451,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in vtDir.Normalize() ; // se la dimensione maggiore è grande come la dimensione dello spazio parametrico allora potrebbe essere che le coordinate parametriche di un vertice // siano da correggere per periodicità + // do per scontato che se la superficie è chiusa lungo un parametro i lati di chiusura non siano dei poli if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) { // trovo se dei vertici del triangolo sono sul bordo dello spazio parametrico INTVECTOR vOn(3) ; fill( vOn.begin(), vOn.end(), -1) ; - int nVertOnPole = -1 ; INTVECTOR vEdgesClosed = { 1, 3} ; // scorro sui vertici for ( int p = 0 ; p < 3; ++p ) { @@ -2416,20 +2463,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for ( int ed : vEdgesClosed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { - if ( ! m_mCCEdge[ed][i]->IsValid()) { - Point3d pt ; - if ( ! m_mCCEdge[ed][i]->GetOnlyPoint(pt)) - return false ; - if ( AreSamePointApprox( pt, vPT[p])) { - vOn[p] = ed ; - // se un vertice sta su un polo me lo segno - nVertOnPole = p ; - } - } - else { - if (m_mCCEdge[ed][i]->IsPointOn(vPT[p]) && vOn[p] == -1 ) - vOn[p] = ed ; - } + if (m_mCCEdge[ed][i]->IsPointOn(vPT[p]) && vOn[p] == -1 ) + vOn[p] = ed ; } } } @@ -2437,9 +2472,9 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate if ( vOn[0] * vOn[1] * vOn[2] < 0 || - (vOn[0] > 0 && vOn[0] != nVertOnPole) || - (vOn[1] > 0 && vOn[1] != nVertOnPole) || - (vOn[2] > 0 && vOn[2] != nVertOnPole)) { + (vOn[0] > 0 && 0 != nVertOnPole) || + (vOn[1] > 0 && 1 != nVertOnPole) || + (vOn[2] > 0 && 2 != nVertOnPole)) { double dRightX ; // tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico for ( int p = 0 ; p < 3; ++p) { @@ -2470,20 +2505,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for (int ed : vEdgesClosed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { - if ( ! m_mCCEdge[ed][i]->IsValid()) { - Point3d pt ; - if ( ! m_mCCEdge[ed][i]->GetOnlyPoint( pt)) - return false ; - if ( AreSamePointApprox( pt, vPT[p])) { - vOn[p] = ed ; - // se un vertice sta su un polo me lo segno - nVertOnPole = p ; - } - } - else { - if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) - vOn[p] = ed ; - } + if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) + vOn[p] = ed ; } } } @@ -2491,9 +2514,9 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate if ( vOn[0] * vOn[1] * vOn[2] < 0 || - (vOn[0] > 0 && vOn[0] != nVertOnPole) || - (vOn[1] > 0 && vOn[1] != nVertOnPole) || - (vOn[2] > 0 && vOn[2] != nVertOnPole)) { + (vOn[0] > 0 && 0 != nVertOnPole) || + (vOn[1] > 0 && 1 != nVertOnPole) || + (vOn[2] > 0 && 2 != nVertOnPole)) { double dRightY ; // tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico for ( int p = 0 ; p < 3; ++p) { @@ -2515,52 +2538,27 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } // devo anche tener conto della possibilità che i lati siano collassati in poli - if ( bIsPole) { - int nInters = -1 ; - for ( int c = 0 ; c < 4 ; ++c) { - if ( ( c == 0 && vInters[0] == vInters[3]) || - ( c != 0 && vInters[c] == vInters[c - 1])){ - nInters = c ; - break ; - } - } - // se non ho trovato il lato su cui ho il polo - if ( nInters == -1) + if ( bIsPole || bNearPole) { + // controllo di aver trovato il lato collassato in polo su cui sta il vertice del triangolo o il punto di intersezione + if ( nEdge == -1) return false ; - // trovo quale vertice è sull'edge di polo - BOOLVECTOR vbOn(3) ; - fill( vbOn.begin(), vbOn.end(), false) ; - for ( int p = 0 ; p < 3; ++p ) { - for ( int c = 0 ; c < 4; ++c) { - for( int i = 0 ; int( m_mCCEdge[c].size()) ; ++i) { - if ( ! m_mCCEdge[c][i]->IsValid()) { - Point3d pt ; - if ( ! m_mCCEdge[c][i]->GetOnlyPoint( pt)) - return false ; - vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; - } - else - vbOn[p] = vbOn[p] || m_mCCEdge[c][i]->IsPointOn( vPT[p]) ; - } - } - } // trovo la coordinata giusta da tenere ( x o y a seconda dell'edge) double dRightX, dRightY ; for ( int p = 0 ; p < 3; ++p) { - if ( ! vbOn[p]) { - if ( nInters == 0 || nInters == 2) { + if ( p != nVertOnPole) { + if ( nEdge == 0 || nEdge == 2) { dRightX = vPtPa[p].x ; - dRightY = nInters == 0 ? dParamH : 0 ; + dRightY = nEdge == 0 ? dParamH : 0 ; } - else if ( nInters == 1 || nInters == 3) { - dRightX = nInters == 1 ? 0 : dParamL ; + else if ( nEdge == 1 || nEdge == 3) { + dRightX = nEdge == 1 ? 0 : dParamL ; dRightY = vPtPa[p].y ; } } } // correggo le coordinate del punto sull'edge di polo for ( int p = 0 ; p < 3 ; ++p) { - if ( vbOn[p]) { + if ( p == nVertOnPole) { vPtPa[p].x = dRightX ; vPtPa[p].y = dRightY ; } From 8f271546047246a404bad86918652486f68197da Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 10 Jun 2024 14:57:28 +0200 Subject: [PATCH 27/45] EgtGeomKernel : - correzione alla conversione di nurbs periodiche in bezier. --- CurveAux.cpp | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index f7ce65e..e4fb728 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -868,26 +868,35 @@ NurbsCurveCanonicalize( CNurbsData& cnData) break ; } } + bool bFirstAddedAtEnd = false ; + bool bRetryKnotsAdjust = false ; if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){ // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped DBLVECTOR vU = cnData.vU ; - // se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo - if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ) { - cnData.vCP.push_back( cnData.vCP[0]) ; - if ( cnData.bRat) - cnData.vW.push_back( cnData.vW[0]) ; - } - // se effettivamente ho dei nodi in più da togliere allora li tolgo - if ( int( cnData.vU.size()) != int(cnData.vCP.size()) + cnData.nDeg - 1) { + // se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo + if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) { + // se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo + if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) { + bFirstAddedAtEnd = true ; + cnData.vCP.push_back( cnData.vCP[0]) ; + if ( cnData.bRat) + cnData.vW.push_back( cnData.vW[0]) ; + } // devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo siano alla fine del vettore dei nodi cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ; // controllo eventualmente anche i nodi extra // se ne ho due in più ne tolgo uno in cima e uno in fondo - if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere + if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere + if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) + bRetryKnotsAdjust = true ; cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; + } // se ne ho solo uno in più lo tolgo in cima - else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) + else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) { + if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) + bRetryKnotsAdjust = true ; cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; + } } // controllo se il vettore dei nodi ha la giusta molteplicità all'inizio e alla fine, sennò ha comunque bisogno di essere resa non periodica double dU0 = cnData.vU[0] ; @@ -901,9 +910,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData) cnData.bPeriodic = false ; return true ; } - else { - // aggiungo i punti ripetuti ( il primo l'ho già aggiunto) - for ( int i = 1 ; i < cnData.nDeg ; ++i ) { + else if ( (int(cnData.vU.size()) != int(cnData.vCP.size()) + cnData.nDeg - 1) || + bRetryKnotsAdjust) { + // aggiungo i punti ripetuti ( controllando se il primo l'ho già aggiunto o c'è già) + bFirstAddedAtEnd = bFirstAddedAtEnd || AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ; + for ( int i = bFirstAddedAtEnd ? 1 : 0 ; i < cnData.nDeg ; ++i ) { cnData.vCP.push_back( cnData.vCP[i]) ; if ( cnData.bRat) cnData.vW.push_back( cnData.vW[i]) ; @@ -925,6 +936,9 @@ NurbsCurveCanonicalize( CNurbsData& cnData) else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } + else { + ; // la nurbs è ancora periodica ma è già pronta per essere resa non periodica + } } } @@ -959,7 +973,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità int b = nU - nDeg - 1 + 1 ; int i = b ; - int c = b ; + //int c = b ; while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO) -- b ; int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg @@ -1034,7 +1048,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // aumento la molteplicità del punto u_p-1 b = nDeg - 1 ; i = b ; - c = b ; + //c = b ; while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO) -- b ; mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg From c637ccec472bbeafadf0c9eb3d33f10aff3a15e3 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 10 Jun 2024 14:57:58 +0200 Subject: [PATCH 28/45] EgtGeomKernel : - aggiunta commento per triangolazione bezier. --- SurfBezier.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d08a966..8f54b90 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1582,6 +1582,9 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const PNTVECTOR vPnt3d ; for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { Point3d pt3d ; + //// NOTA PER MIGLIORAMENTO + // i punti nello spazio 3D che calcolo qui in realtà li ho già calcolati durante la costruzione dell'albero!!! + // devo trovare il modo di passarli fino a qui, tenendo conto anche che potrebbero esserci più alberi!! if ( ! GetPointD1D2( vPnt[i].x / SBZ_TREG_COEFF, vPnt[i].y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d)) return nullptr ; vPnt3d.push_back( pt3d) ; From 36ce855ef3e50c89541cd6b797fb84549a71237d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 11 Jun 2024 15:55:56 +0200 Subject: [PATCH 29/45] EgtGeomKernel : - correzione alla conversione di nurbs periodiche. --- CurveAux.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index e4fb728..ec97ccf 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -858,9 +858,10 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // se periodica if ( cnData.bPeriodic || ! cnData.bClamped) { + bool bAlreadyChecked = false ; // se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva // wrap della curva su se stessa - if ( cnData.bPeriodic ) { + if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) { bool bRepeated = true ; for ( int i = 0 ; i < cnData.nDeg ; ++i) { if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) { @@ -869,7 +870,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) } } bool bFirstAddedAtEnd = false ; - bool bRetryKnotsAdjust = false ; + //bool bRetryKnotsAdjust = false ; if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){ // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped DBLVECTOR vU = cnData.vU ; @@ -887,14 +888,14 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // controllo eventualmente anche i nodi extra // se ne ho due in più ne tolgo uno in cima e uno in fondo if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere - if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) - bRetryKnotsAdjust = true ; + //if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) + // bRetryKnotsAdjust = true ; cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; } // se ne ho solo uno in più lo tolgo in cima else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) { - if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) - bRetryKnotsAdjust = true ; + //if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) + // bRetryKnotsAdjust = true ; cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } } @@ -910,8 +911,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) cnData.bPeriodic = false ; return true ; } - else if ( (int(cnData.vU.size()) != int(cnData.vCP.size()) + cnData.nDeg - 1) || - bRetryKnotsAdjust) { + else /*if ( bRetryKnotsAdjust )*/ { // aggiungo i punti ripetuti ( controllando se il primo l'ho già aggiunto o c'è già) bFirstAddedAtEnd = bFirstAddedAtEnd || AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ; for ( int i = bFirstAddedAtEnd ? 1 : 0 ; i < cnData.nDeg ; ++i ) { @@ -936,9 +936,25 @@ NurbsCurveCanonicalize( CNurbsData& cnData) else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } - else { - ; // la nurbs è ancora periodica ma è già pronta per essere resa non periodica - } + //else { + // ; // la nurbs è ancora periodica ma è già pronta per essere resa non periodica + //} + bAlreadyChecked = true ; + } + } + + if ( ! bAlreadyChecked) { + // se non ho già controllato guardo se ho già la giusta molteplicità all'inizio e alla fine del vettore dei nodi + double dU0 = cnData.vU[0] ; + double dULast = cnData.vU.back() ; + bool bSame = true ; + for ( int i = 1 ; i < cnData.nDeg ; ++i ) { + bSame = bSame && abs(cnData.vU[i] - dU0) < EPS_SMALL ; + bSame = bSame && abs(cnData.vU.end()[-( i+ 1)] - dULast) < EPS_SMALL ; + } + if ( bSame) { + cnData.bPeriodic = false ; + return true ; } } From 9a29ee0e27dc289338d2b1b89cdd1aaaef8b4f21 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 12 Jun 2024 09:19:28 +0200 Subject: [PATCH 30/45] EgtGeomKernel : - pulizia codice. --- CurveAux.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index ec97ccf..e3b4581 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -870,7 +870,6 @@ NurbsCurveCanonicalize( CNurbsData& cnData) } } bool bFirstAddedAtEnd = false ; - //bool bRetryKnotsAdjust = false ; if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){ // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped DBLVECTOR vU = cnData.vU ; @@ -888,14 +887,10 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // controllo eventualmente anche i nodi extra // se ne ho due in più ne tolgo uno in cima e uno in fondo if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere - //if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) - // bRetryKnotsAdjust = true ; cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; } // se ne ho solo uno in più lo tolgo in cima else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) { - //if( abs( cnData.vU[0] - cnData.vU[1]) < EPS_SMALL ) - // bRetryKnotsAdjust = true ; cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } } @@ -911,7 +906,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) cnData.bPeriodic = false ; return true ; } - else /*if ( bRetryKnotsAdjust )*/ { + else { // aggiungo i punti ripetuti ( controllando se il primo l'ho già aggiunto o c'è già) bFirstAddedAtEnd = bFirstAddedAtEnd || AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ; for ( int i = bFirstAddedAtEnd ? 1 : 0 ; i < cnData.nDeg ; ++i ) { @@ -936,9 +931,6 @@ NurbsCurveCanonicalize( CNurbsData& cnData) else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } - //else { - // ; // la nurbs è ancora periodica ma è già pronta per essere resa non periodica - //} bAlreadyChecked = true ; } } From 09220bfd68642b08e2fb9e0a3d6995595abe6866 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 12 Jun 2024 15:18:27 +0200 Subject: [PATCH 31/45] EgtGeomKernel : - correzione all'utlima modifica alla triangolazione delle bezier. --- SurfBezier.cpp | 7 +--- Tree.cpp | 105 +++++++++++++++++++++++++------------------------ Tree.h | 5 ++- 3 files changed, 58 insertions(+), 59 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 8f54b90..051c639 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1519,7 +1519,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const // costruttore della superficie POLYLINEMATRIX vvPL ; //POLYLINEVECTOR vPL ; // per usare i polygon basic - //Tree Tree( this, true) ; Tree Tree ; if ( ! Tree.SetSurf( this, true)) return nullptr ; @@ -1546,7 +1545,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const } if ( ! Tree.GetPolygons( vvPL)) continue ; - //Tree.GetPolygonsBasic( vPL) ; // per usare i polygon basic + //Tree.GetPolygonsBasic( vPL, true) ; // per usare i polygon basic // aggiorno la chiusura della superficie m_bClosedU = m_bClosedU || Tree.IsClosedU() ; @@ -1570,7 +1569,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const return nullptr ; // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d - int c = 0 ; for ( POLYLINEVECTOR vPL : vvPL) { PNTVECTOR vPnt ; INTVECTOR vTria ; @@ -1597,7 +1595,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const vPnt[vTria[3*i+2]].x, vPnt[vTria[3*i+2]].y)) return nullptr ; } - ++c ; } // termino @@ -1761,7 +1758,6 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& if ( bThroughEdge) { // devo cambiare le coordinate di pt2DPrev per periodicità // capisco su quale lato è e lo porto sul lato opposto - Point3d pt = pt2DPrev ; if ( m_bClosedU) { if ( pt2DPrev.x < 1) pt2DPrev.x = m_nSpanU * SBZ_TREG_COEFF ; @@ -3466,7 +3462,6 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V IntersCurveCurve icc( *pCurve, *pAx) ; Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Point3d ptEnd ; pCurve->GetStartPoint( ptEnd) ; - int nPrevType = 0 ; for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i) { IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( i, iccInfo) ; diff --git a/Tree.cpp b/Tree.cpp index f005dbe..96b1a30 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1573,7 +1573,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) if ( ! m_bTrimmed) { vPolygons.clear() ; POLYLINEVECTOR vPolygonsBasic ; - GetPolygonsBasic( vPolygonsBasic) ; + GetPolygonsBasic( vPolygonsBasic, true) ; for ( PolyLine pl : vPolygonsBasic) { POLYLINEVECTOR vSinglePolygon ; vSinglePolygon.push_back( pl) ; @@ -1639,12 +1639,13 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVECTOR vCells) { // condizioni per il calcolo dei poligoni di base if ( m_vPolygons.empty() || // se non li ho mai calcolati ( ! m_vPolygons.empty() && ! vCells.empty()) || // se ho già calcolato dei poligoni ma ne sto chiedendo di un altro gruppo di celle - ( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size())) { // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle + ( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size()) || // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle + bForTriangulation) { // oppure se sto chiedendo i poligoni per la triangolazione ( devo fare considerazioni particolari se ho dei poli sui lati del parametrico) m_vPolygons.clear() ; // se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie if ( vCells.empty()) @@ -1778,53 +1779,55 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; vnVert.push_back( int(vVertices.size()) - 1) ; - // ora devo controllare se uno dei lati della cella è collassato in un punto. - // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra - // se ne ho messi solo su uno dei due allora devo togliere il vertice dell'altro lato - if ( AreSamePointApprox(m_mVert.at(nId).at(0), m_mVert.at(nId).at(1)) && ( vbBonusVert[1] || vbBonusVert[3])) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if( ! ( vbBonusVert[1] && vbBonusVert[3])){ - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if( vbBonusVert[1]) // lati contati a partire da quello sopra in senso CCW - vVertices.erase( vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - else if ( vbBonusVert[3]) { - // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVertices.pop_back() ; - vVertices[0] = vVertices.end()[-1] ; + if ( bForTriangulation){ + // ora devo controllare se uno dei lati della cella è collassato in un punto. + // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra + // se ne ho messi solo su uno dei due allora devo togliere il vertice dell'altro lato + if ( AreSamePointApprox(m_mVert.at(nId).at(0), m_mVert.at(nId).at(1)) && ( vbBonusVert[1] || vbBonusVert[3] ) ) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[1] ) // lati contati a partire da quello sopra in senso CCW + vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + else if ( vbBonusVert[3] ) { + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVertices.pop_back() ; + vVertices[0] = vVertices.end()[-1] ; + } } } - } - if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2)) && ( vbBonusVert[0] || vbBonusVert[2])) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if( ! ( vbBonusVert[0] && vbBonusVert[2])){ - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if( vbBonusVert[0]) // lati contati a partire da quello sopra in senso CCW - vVertices.erase( vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - else if ( vbBonusVert[2]) - vVertices.erase( vVertices.begin() + vnVert[2]) ; - } - } - if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3)) && ( vbBonusVert[1] || vbBonusVert[3])) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if( ! ( vbBonusVert[1] && vbBonusVert[3])){ - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if( vbBonusVert[1]) // lati contati a partire da quello sopra in senso CCW - vVertices.erase( vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW - else if ( vbBonusVert[3]) - vVertices.erase( vVertices.begin() + vnVert[3]) ; - } - } - if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0)) && ( vbBonusVert[0] || vbBonusVert[2])) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if( ! ( vbBonusVert[0] && vbBonusVert[2])){ - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if( vbBonusVert[0]){ // lati contati a partire da quello sopra in senso CCW - // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVertices.pop_back() ; - vVertices[0] = vVertices.end()[-1] ; + if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2)) && ( vbBonusVert[0] || vbBonusVert[2] ) ) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[0] ) // lati contati a partire da quello sopra in senso CCW + vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + else if ( vbBonusVert[2] ) + vVertices.erase(vVertices.begin() + vnVert[2]) ; + } + } + if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3)) && ( vbBonusVert[1] || vbBonusVert[3] ) ) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[1] ) // lati contati a partire da quello sopra in senso CCW + vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW + else if ( vbBonusVert[3] ) + vVertices.erase(vVertices.begin() + vnVert[3]) ; + } + } + if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0)) && ( vbBonusVert[0] || vbBonusVert[2] ) ) { + // se ho punti bonus su entrambi i lati non devo fare nulla + if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[0] ) { // lati contati a partire da quello sopra in senso CCW + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVertices.pop_back() ; + vVertices[0] = vVertices.end()[-1] ; + } + else if ( vbBonusVert[2] ) + vVertices.erase(vVertices.begin() + vnVert[3]) ; } - else if ( vbBonusVert[2]) - vVertices.erase( vVertices.begin() + vnVert[3]) ; } } @@ -3896,13 +3899,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) // recupero i poligoni base delle celle sui bordi POLYLINEMATRIX mPL ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[0], vEdges[0]) ; + GetPolygonsBasic( mPL[0], false, vEdges[0]) ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[1], vEdges[1]) ; + GetPolygonsBasic( mPL[1], false, vEdges[1]) ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[2], vEdges[2]) ; + GetPolygonsBasic( mPL[2], false, vEdges[2]) ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[3], vEdges[3]) ; + GetPolygonsBasic( mPL[3], false, vEdges[3]) ; // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato for ( int i = 0 ; i < int( mPL.size()) ; ++i) { diff --git a/Tree.h b/Tree.h index da3042a..e5ffece 100644 --- a/Tree.h +++ b/Tree.h @@ -239,8 +239,9 @@ class Tree // dSideMin è lunghezza minima del lato di una cella nello spazio reale bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; bool GetPolygons( POLYLINEMATRIX& vPolygons) ; - bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero - // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bFroTriangulation = false, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero + // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati + // se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle From 9d845179a4e918bf3093c56d94c4d7502a863a3d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 19 Jun 2024 10:07:03 +0200 Subject: [PATCH 32/45] =?UTF-8?q?EgtGeomKernel=20:=20-=20migliormaneto=20d?= =?UTF-8?q?ella=20velocit=C3=A0=20di=20calcolo=20per=20la=20triangolazione?= =?UTF-8?q?=20di=20superfici=20di=20Bezier.=20-=20irrobustimento=20della?= =?UTF-8?q?=20stessa=20triangolazione.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 48 ++++++-- Tree.cpp | 327 ++++++++++++++++++++++++++++++++++++++----------- Tree.h | 19 +-- 3 files changed, 306 insertions(+), 88 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 051c639..089ec0e 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1518,6 +1518,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const // costruttore della superficie POLYLINEMATRIX vvPL ; + POLYLINEMATRIX vvPL3d ; //POLYLINEVECTOR vPL ; // per usare i polygon basic Tree Tree ; if ( ! Tree.SetSurf( this, true)) @@ -1543,7 +1544,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const Tree.BuildTree( dTol, dSideMin) ; //Tree.BuildTree( 1, 5) ; //debug } - if ( ! Tree.GetPolygons( vvPL)) + if ( ! Tree.GetPolygons( vvPL, vvPL3d)) continue ; //Tree.GetPolygonsBasic( vPL, true) ; // per usare i polygon basic @@ -1569,6 +1570,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const return nullptr ; // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d + int c = 0 ; for ( POLYLINEVECTOR vPL : vvPL) { PNTVECTOR vPnt ; INTVECTOR vTria ; @@ -1576,17 +1578,44 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const if ( ! Tri.Make( vPL, vPnt, vTria)) return nullptr ; + //vedo se la polyline 3d che passo io corrisponde a quella che usavo prima + POLYLINEVECTOR vPL3d = vvPL3d[c] ; + // porto i punti in 3d PNTVECTOR vPnt3d ; - for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { - Point3d pt3d ; - //// NOTA PER MIGLIORAMENTO - // i punti nello spazio 3D che calcolo qui in realtà li ho già calcolati durante la costruzione dell'albero!!! - // devo trovare il modo di passarli fino a qui, tenendo conto anche che potrebbero esserci più alberi!! - if ( ! GetPointD1D2( vPnt[i].x / SBZ_TREG_COEFF, vPnt[i].y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d)) - return nullptr ; - vPnt3d.push_back( pt3d) ; + + for( int i = 0 ; i < int( vPL3d.size()) ; ++i) { + PolyLine pl3d = vPL3d[i] ; + Point3d pt3d ; pl3d.GetFirstPoint( pt3d) ; + //vPnt3d.push_back( pt3d) ; + while ( pl3d.GetNextPoint( pt3d)) { + vPnt3d.push_back( pt3d) ; + } } + + // controllo per ogni polyline se è stato invertito il vettore dei punti + int nCurrPoint = 0 ; + for( int i = 0 ; i < int( vPL.size()) ; ++i) { + Point3d pt3d ; vPL[i].GetFirstPoint( pt3d) ; + vPL[i].GetNextPoint( pt3d) ; + int nPoints = vPL[i].GetPointNbr() - 2 ; + if ( ! AreSamePointApprox( vPnt[nCurrPoint], pt3d)) + reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; + nCurrPoint += nPoints ; + } + + //controllo che i due vettori vPnt e vPnt3d abbiano la stessa lunghezza, sennò vuol dire che nel vettore vPnt3d ho avuto dei Rejected e devo ricalcolarli + // i punti in eccesso verranno poi scartati dalla trimesh + if( vPnt.size() != vPnt3d.size()) { + vPnt3d.clear() ; + for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { + Point3d pt3d ; + if ( ! GetPointD1D2( vPnt[i].x / SBZ_TREG_COEFF, vPnt[i].y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d)) + return nullptr ; + vPnt3d.push_back( pt3d) ; + } + } + int nTria = int( vTria.size()) / 3 ; for ( int i = 0 ; i < nTria ; ++i) { if ( ! stmSoup.AddTriangle( vPnt3d[vTria[3*i]], vPnt3d[vTria[3*i+1]], vPnt3d[vTria[3*i+2]], @@ -1595,6 +1624,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const vPnt[vTria[3*i+2]].x, vPnt[vTria[3*i+2]].y)) return nullptr ; } + ++c ; } // termino diff --git a/Tree.cpp b/Tree.cpp index 96b1a30..227a65f 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1567,24 +1567,54 @@ Tree::GetDepth( int nId, int nRef = -2) const //---------------------------------------------------------------------------- bool -Tree::GetPolygons( POLYLINEMATRIX& vPolygons) +Tree::GetPolygons( POLYLINEMATRIX& vvPolygons) +{ + POLYLINEMATRIX vvPolygonsBasic3d ; + return GetPolygons( vvPolygons, false, vvPolygonsBasic3d) ; +} + +//---------------------------------------------------------------------------- +bool +Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vPolygonsBasic3d) +{ + return GetPolygons( vvPolygons, true, vPolygonsBasic3d) ; +} + +//---------------------------------------------------------------------------- +bool +Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) { if ( (int) m_vPolygons.size() == 0) { if ( ! m_bTrimmed) { - vPolygons.clear() ; + vvPolygons.clear() ; POLYLINEVECTOR vPolygonsBasic ; - GetPolygonsBasic( vPolygonsBasic, true) ; + POLYLINEVECTOR vPolygonsBasic3d ; + if ( bForTriangulation) + GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ; + else + GetPolygonsBasic( vPolygonsBasic) ; + int c = 0; for ( PolyLine pl : vPolygonsBasic) { POLYLINEVECTOR vSinglePolygon ; vSinglePolygon.push_back( pl) ; - vPolygons.push_back( vSinglePolygon) ; + vvPolygons.push_back( vSinglePolygon) ; + if ( bForTriangulation) { + POLYLINEVECTOR vSinglePolygon3d ; + vSinglePolygon3d.push_back( vPolygonsBasic3d[c]) ; + vvPolygons3d.push_back( vSinglePolygon3d) ; + } + ++c ; } return true ; } // trimmata else { POLYLINEVECTOR vPolygonsBasic ; - GetPolygonsBasic( vPolygonsBasic) ; + POLYLINEVECTOR vPolygonsBasic3d ; + if ( bForTriangulation) + GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ; + else + GetPolygonsBasic( vPolygonsBasic) ; // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim m_vCEdge2D.clear() ; for ( int i = 0 ; i < 4 ; ++i) { @@ -1603,7 +1633,17 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) // vettore dei poligoni ( loop) della cella nId POLYLINEVECTOR vCellPolygons ; vCellPolygons.push_back( vPolygonsBasic[i]) ; - vPolygons.push_back( vCellPolygons) ; + vvPolygons.push_back( vCellPolygons) ; + if ( bForTriangulation ) { + POLYLINEVECTOR vCellPolygons3d ; + PolyLine plPolygon3d ; + plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ; + plPolygon3d.AddUPoint( 1, m_mVert[nId][1]) ; + plPolygon3d.AddUPoint( 2, m_mVert[nId][2]) ; + plPolygon3d.AddUPoint( 3, m_mVert[nId][3]) ; + vCellPolygons3d.push_back( plPolygon3d) ; + vvPolygons3d.push_back( vCellPolygons3d) ; + } } else if ( m_mTree[nId].m_nFlag == 0) continue ; @@ -1620,26 +1660,41 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) // in questo for analizzo solo i loop che tagliano la cella while( (int)vToCheck.size() != 0) { int nPolyBefore = nPoly ; - CreateCellPolygons( i, vPolygons, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i]) ; + CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i], vPolygonsBasic3d[i]) ; if ( nPolyBefore == nPoly) break ; } // ora analizzo anche i loop che sono contenuti nella cella - CreateIslandAndHoles( i, vPolygons, nPoly, vnParentChunk) ; + CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk) ; } } return true ; } } else { - vPolygons = m_vPolygons ; + vvPolygons = m_vPolygons ; return true ; } } //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVECTOR vCells) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygons3d) +{ + return GetPolygonsBasic( vPolygons, true, vPolygons3d) ; +} + +//---------------------------------------------------------------------------- +bool +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) +{ + POLYLINEVECTOR vPolygons3d ; + return GetPolygonsBasic( vPolygons, false, vPolygons3d, vCells) ; +} + +//---------------------------------------------------------------------------- +bool +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells) { // condizioni per il calcolo dei poligoni di base if ( m_vPolygons.empty() || // se non li ho mai calcolati @@ -1647,11 +1702,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE ( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size()) || // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle bForTriangulation) { // oppure se sto chiedendo i poligoni per la triangolazione ( devo fare considerazioni particolari se ho dei poli sui lati del parametrico) m_vPolygons.clear() ; + m_vPolygons3d.clear() ; // se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie if ( vCells.empty()) vCells = m_vnLeaves ; PNTVECTOR vVertices ; + PNTVECTOR vVertices3d ; INTVECTOR vNeigh ; // setto le celle che sono sul LeftEdge e sul TopEdge if ( m_bClosedU) { @@ -1673,8 +1730,10 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE // N.B. :i poligoni sono costruiti a partire dal ptBL !!! for ( int nId : vCells) { vVertices.clear() ; + vVertices3d.clear() ; vNeigh.clear() ; vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + vVertices3d.push_back( m_mVert.at( nId)[0]) ; INTVECTOR vnVert ; BOOLVECTOR vbBonusVert(4) ; fill( vbBonusVert.begin(), vbBonusVert.end(), false) ; @@ -1688,11 +1747,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; vVertices.push_back( pt) ; + vVertices3d.push_back( m_mVert[j][1]) ; } } else { - for ( int j : vNeigh) + for ( int j : vNeigh) { vVertices.push_back( m_mTree.at( j).GetTopRight()) ; + vVertices3d.push_back( m_mVert[j][2]) ; + } } bBottomRight = true ; vbBonusVert[2] = true ; @@ -1710,11 +1772,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; vVertices.push_back( pt) ; + vVertices3d.push_back( m_mVert[j][1]) ; } } else { - for ( int j : vNeigh) + for ( int j : vNeigh) { vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ; + vVertices3d.push_back( m_mVert[j][0]) ; + } } vbBonusVert[3] = true ; } @@ -1722,10 +1787,12 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE else if ( ! bBottomRight) { Point3d ptBr( m_mTree.at( nId).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; vVertices.push_back( ptBr) ; + vVertices3d.push_back( m_mVert[nId][1]) ; vnVert.push_back( int(vVertices.size()) - 1) ; } vNeigh.clear() ; vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; + vVertices3d.push_back( m_mVert[nId][2]) ; vnVert.push_back( int(vVertices.size()) - 1) ; GetTopNeigh ( nId, vNeigh) ; std::reverse( vNeigh.begin(), vNeigh.end()) ; @@ -1738,11 +1805,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; vVertices.push_back( pt) ; + vVertices3d.push_back( m_mVert[j][3]) ; } } else { - for ( int j : vNeigh) + for ( int j : vNeigh) { vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ; + vVertices3d.push_back( m_mVert[j][0]) ; + } } bTopLeft = true ; vbBonusVert[0] = true ; @@ -1761,11 +1831,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; vVertices.push_back( pt) ; + vVertices3d.push_back( m_mVert[j][3]) ; } } else { - for ( int j : vNeigh) + for ( int j : vNeigh) { vVertices.push_back( m_mTree.at( j).GetTopRight()) ; + vVertices3d.push_back( m_mVert[j][2]) ; + } } vbBonusVert[1] = true ; } @@ -1773,10 +1846,12 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE else if ( ! bTopLeft) { Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; vVertices.push_back( ptTl) ; + vVertices3d.push_back( m_mVert[nId][3]) ; vnVert.push_back( int(vVertices.size()) - 1) ; } vNeigh.clear() ; vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + vVertices3d.push_back( m_mVert[nId][0]) ; vnVert.push_back( int(vVertices.size()) - 1) ; if ( bForTriangulation){ @@ -1787,12 +1862,16 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[1] ) // lati contati a partire da quello sopra in senso CCW + if ( vbBonusVert[1] ) {// lati contati a partire da quello sopra in senso CCW vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + } else if ( vbBonusVert[3] ) { // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto vVertices.pop_back() ; vVertices[0] = vVertices.end()[-1] ; + vVertices3d.pop_back() ; + vVertices3d[0] = vVertices3d.end()[-1] ; } } } @@ -1800,20 +1879,28 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[0] ) // lati contati a partire da quello sopra in senso CCW + if ( vbBonusVert[0] ){ // lati contati a partire da quello sopra in senso CCW vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - else if ( vbBonusVert[2] ) + vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + } + else if ( vbBonusVert[2] ){ vVertices.erase(vVertices.begin() + vnVert[2]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + } } } if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3)) && ( vbBonusVert[1] || vbBonusVert[3] ) ) { // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[1] ) // lati contati a partire da quello sopra in senso CCW + if ( vbBonusVert[1] ){ // lati contati a partire da quello sopra in senso CCW vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW - else if ( vbBonusVert[3] ) + vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + } + else if ( vbBonusVert[3] ) { vVertices.erase(vVertices.begin() + vnVert[3]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + } } } if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0)) && ( vbBonusVert[0] || vbBonusVert[2] ) ) { @@ -1824,9 +1911,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto vVertices.pop_back() ; vVertices[0] = vVertices.end()[-1] ; + vVertices3d.pop_back() ; + vVertices3d[0] = vVertices3d.end()[-1] ; } - else if ( vbBonusVert[2] ) + else if ( vbBonusVert[2] ) { vVertices.erase(vVertices.begin() + vnVert[3]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + } } } } @@ -1850,14 +1941,19 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE if ( Dist( ptP00P11, ptPSrf) + EPS_SMALL > Dist( ptP10P01, ptPSrf)) { rotate( vVertices.begin(), vVertices.begin() + 1,vVertices.end()) ; vVertices.back() = vVertices.at( 0) ; + rotate( vVertices3d.begin(), vVertices3d.begin() + 1,vVertices3d.end()) ; + vVertices3d.back() = vVertices3d.at( 0) ; } } } m_vPolygons.emplace_back() ; m_vPolygons.back().emplace_back() ; + m_vPolygons3d.emplace_back() ; + m_vPolygons3d.back().emplace_back() ; for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { m_vPolygons.back().back().AddUPoint( i, vVertices.at( i)) ; + m_vPolygons3d.back().back().AddUPoint( i, vVertices3d.at( i)) ; } } @@ -1867,6 +1963,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE for ( int t = 0 ; t < (int)m_vPolygons.size() ; ++ t) { for ( int z = 0 ; z < (int)m_vPolygons[t].size() ; ++z) { vPolygons.push_back( m_vPolygons[t][z]) ; + vPolygons3d.push_back( m_vPolygons3d[t][z]) ; } } return true ; @@ -2172,7 +2269,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva while ( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) { // sto uscendo dalla cella, quindi cerco l'intersezione - if ( bEraseNextPoint) { + if ( bEraseNextPoint && vptInters.size() != 0) { vptInters.pop_back() ; bEraseNextPoint = false ; } @@ -2182,7 +2279,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // al precedente FindInters avrei dovuto passare di cella if ( ! FindInters( nId, clTrim, vptInters, true)) { // scarterò il punto molto vicino al lato e tengo solo l'intersezione del trim col lato - vptInters.pop_back() ; + if( vptInters.size() != 0) + vptInters.pop_back() ; plLoop.GetPrevPoint( ptTEnd) ; plLoop.GetPrevPoint( ptTStart) ; plLoop.GetNextPoint( ptCurr) ; @@ -2203,10 +2301,19 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // aggiorno la polyline splittata UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ; } - // aggiungo la fine del segmento nel vettore delle intersezioni - vptInters.push_back( ptCurr) ; - // aggiorno la polyline splittata - UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; + // VERSIONE NUOVA + // controllo di aggiungere un punto abbastanza distante dal precedente + if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 2 * EPS_SMALL)) { + // aggiungo la fine del segmento nel vettore delle intersezioni + vptInters.push_back( ptCurr) ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; + } + ////VECCHIA VERSIONE + //// aggiungo la fine del segmento nel vettore delle intersezioni + //vptInters.push_back( ptCurr) ; + //// aggiorno la polyline splittata + //UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; } if ( nId == nFirstCell) vptInters.pop_back() ; @@ -2519,7 +2626,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool else if ( nEdge == 7) ptInters = ptTR ; // aggiungo il nuovo punto al vettore delle intersezioni - if ( (int)vptInters.size() == 0 || ! AreSamePointApprox( ptInters , vptInters.back())) + if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 2 * EPS_SMALL)) vptInters.push_back( ptInters) ; else { // se l'ultimo punto del vettore delle intersezioni è quasi uguale al punto che devo aggiungere allora lo sostituisco con quest'ultimo @@ -2834,21 +2941,20 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool //---------------------------------------------------------------------------- bool -Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) +Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) { // conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato int nId = m_vnLeaves[nLeafId] ; - PNTMATRIX vEdgeVertex ; - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - vEdgeVertex.emplace_back() ; - vEdgeVertex.back().push_back( m_mTree[nId].GetTopRight()) ; - vEdgeVertex.emplace_back() ; - vEdgeVertex.back().push_back( ptTl) ; - vEdgeVertex.emplace_back() ; - vEdgeVertex.back().push_back( m_mTree[nId].GetBottomLeft()) ; - vEdgeVertex.emplace_back() ; - vEdgeVertex.back().push_back( ptBr) ; + PNTMATRIX vEdgeVertex(4) ; + PNTMATRIX vEdgeVertex3d(4) ; + vEdgeVertex[0].push_back( m_mTree[nId].GetTopRight()) ; + vEdgeVertex[1].push_back( m_mTree[nId].GetTopLeft()) ; + vEdgeVertex[2].push_back( m_mTree[nId].GetBottomLeft()) ; + vEdgeVertex[3].push_back( m_mTree[nId].GetBottomRight()) ; + vEdgeVertex3d[0].push_back( m_mVert[nId][2]) ; + vEdgeVertex3d[1].push_back( m_mVert[nId][3]) ; + vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ; + vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ; // la PolyLine è riempita a partire dal lato bottom Point3d ptStart ; plCell.GetFirstPoint( ptStart) ; @@ -2868,8 +2974,10 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo INTVECTOR vToCheckNow = vToCheck ; // vettore dei poligoni ( loop) della cella nId POLYLINEVECTOR vCellPolygons ; + POLYLINEVECTOR vCellPolygons3d ; // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps PolyLine plTrimmedPoly ; + PolyLine plTrimmedPoly3d ; // numero di volte che la cella è stata attraversata da una curva di trim int nPassToCheck = (int) vToCheckNow.size() ; // numero di vertici aggiunti al nuovo poligono @@ -2894,7 +3002,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo nFirstLoopInPoly = j ; } for ( Point3d ptInt : inA.vpt) { - AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptInt) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptInt, plTrimmedPoly3d) ; } vAddedLoops.push_back( j) ; nEdge = inA.nOut ; @@ -2948,6 +3056,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo vEdge.Set( 1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; + plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 0 ; } } @@ -2956,6 +3065,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo vEdge.Set( 0,-1,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; + plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 1 ; } } @@ -2964,6 +3074,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo vEdge.Set( -1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; + plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 2 ; } } @@ -2972,6 +3083,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo vEdge.Set( 0,1,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; + plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 3 ; } } @@ -2980,6 +3092,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo // quindi salto al prossimo loop if ( plTrimmedPoly.GetPointNbr() == 1) { plTrimmedPoly.Clear() ; + plTrimmedPoly3d.Clear() ; if ( j == nFirstLoopInPoly) nEdgeIn = -1 ; continue ; @@ -3015,14 +3128,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo while ( ! ( bValidNextStart && bAtNextStart) && bNotCameBack) { Point3d ptVert ; if ( nEdge == 0) - ptVert = ptTl ; + ptVert = vEdgeVertex[1][0] ; else if ( nEdge == 1) - ptVert = m_mTree[nId].GetBottomLeft() ; + ptVert = vEdgeVertex[2][0] ; else if ( nEdge == 2) - ptVert = ptBr ; + ptVert = vEdgeVertex[3][0] ; else if ( nEdge == 3) - ptVert = m_mTree[nId].GetTopRight() ; - AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ; + ptVert = vEdgeVertex[0][0] ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3) @@ -3069,14 +3182,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo while ( bNotCameBack) { Point3d ptVert ; if ( nEdge == 0) - ptVert = ptTl ; + ptVert = vEdgeVertex[1][0] ; else if ( nEdge == 1) - ptVert = m_mTree[nId].GetBottomLeft() ; + ptVert = vEdgeVertex[2][0] ; else if ( nEdge == 2) - ptVert = ptBr ; + ptVert = vEdgeVertex[3][0] ; else if ( nEdge == 3) - ptVert = m_mTree[nId].GetTopRight() ; - AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ; + ptVert = vEdgeVertex[0][0] ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3) @@ -3095,6 +3208,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo } plTrimmedPoly.Close() ; + plTrimmedPoly3d.Close() ; // controllo sull'area del poligono, se è 0 ( quindi un segmento), non lo aggiungo double dArea ; plTrimmedPoly.GetAreaXY( dArea) ; @@ -3102,13 +3216,17 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo if ( dArea > 0) { vCellPolygons.push_back( plTrimmedPoly) ; vPolygons.push_back( vCellPolygons) ; + vCellPolygons3d.push_back( plTrimmedPoly3d) ; + vPolygons3d.push_back( vCellPolygons3d) ; ++ nPoly ; vnParentChunk.push_back( inA.nChunk) ; vCellPolygons.clear() ; + vCellPolygons3d.clear() ; } c = 0 ; plTrimmedPoly.Clear() ; + plTrimmedPoly3d.Clear() ; nEdgeIn = -1 ; // devo verificare se tra i loop che sono finiti in vToCheck in realtà qualcuno l'ho usato per fare un poligono for ( int k = 0 ; k < (int)vToCheck.size() ; ++ k) { @@ -3127,18 +3245,21 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo //---------------------------------------------------------------------------- bool -Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) +Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk) { // vettore dei poligoni ( loop) della cella nId POLYLINEVECTOR vCellPolygons ; + POLYLINEVECTOR vCellPolygons3d ; // costruisco i poligoni partendo dal vettore delle intersezioni int nId = m_vnLeaves[nLeafId] ; - PolyLine plTrimmedPoly ; + //PolyLine plTrimmedPoly ; + //PolyLine plTrimmedPoly3d ; // loop interni in una cella intersecata int nChunkBiggestCW = -1 ; if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) { PolyLine plInLoop ; + PolyLine plInLoop3d ; Inters inA ; // se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW devo aggiungere il bordo bool bAllContained = true ; @@ -3175,18 +3296,24 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella Point3d ptVert = m_mTree[nId].GetTopRight() ; plInLoop.AddUPoint( 0, ptVert) ; - ptVert.x = m_mTree[nId].GetBottomLeft().x ; - ptVert.y = m_mTree[nId].GetTopRight().y ; + ptVert = m_mTree[nId].GetTopLeft() ; plInLoop.AddUPoint( 1, ptVert) ; ptVert = m_mTree[nId].GetBottomLeft() ; plInLoop.AddUPoint( 2, ptVert) ; - ptVert.x = m_mTree[nId].GetTopRight().x ; - ptVert.y = m_mTree[nId].GetBottomLeft().y ; + ptVert = m_mTree[nId].GetBottomRight() ; plInLoop.AddUPoint( 3, ptVert) ; plInLoop.Close() ; vCellPolygons.push_back( plInLoop) ; vPolygons.push_back( vCellPolygons) ; ++ nPoly ; + plInLoop3d.AddUPoint( 0, m_mVert[nId][2]); + plInLoop3d.AddUPoint( 1, m_mVert[nId][3]); + plInLoop3d.AddUPoint( 2, m_mVert[nId][0]); + plInLoop3d.AddUPoint( 3, m_mVert[nId][1]); + vCellPolygons3d.push_back( plInLoop3d) ; + vPolygons3d.push_back( vCellPolygons3d) ; + vCellPolygons3d.clear() ; + plInLoop3d.Clear() ; // imposto il chunk del loop CW più grande ( il primo che ho incontrato) vnParentChunk.push_back( nChunkBiggestCW) ; vCellPolygons.clear() ; @@ -3199,9 +3326,12 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, int k = 0 ; for ( Point3d ptInt : inA.vpt) { plInLoop.AddUPoint( k, ptInt) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptInt.x / SBZ_TREG_COEFF, ptInt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plInLoop3d.AddUPoint( k, pt3d) ; ++ k ; } plInLoop.Close() ; + plInLoop3d.Close() ; bool bAdded = false ; // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto if ( ! inA.bCCW) { @@ -3211,7 +3341,9 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, for ( int r = 0 ; r < nPoly ; ++r) { if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk) { vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ; + vPolygons3d[nOtherPoly - r - 1].push_back( plInLoop3d) ; plInLoop.Clear() ; + plInLoop3d.Clear() ; bAdded = true ; break ; } @@ -3220,12 +3352,17 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, if ( ! bAdded) { vCellPolygons.push_back( plInLoop) ; vPolygons.push_back( vCellPolygons) ; + vCellPolygons3d.push_back( plInLoop3d) ; + vPolygons3d.push_back( vCellPolygons3d) ; ++ nPoly ; vnParentChunk.push_back( inA.nChunk) ; plInLoop.Clear() ; vCellPolygons.clear() ; + plInLoop3d.Clear() ; + vCellPolygons3d.clear() ; } plInLoop.Clear() ; + plInLoop3d.Clear() ; } else continue ; @@ -3384,11 +3521,14 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const //---------------------------------------------------------------------------- bool -Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const +Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d) const { // se è il primo punto della PolyLine lo aggiungo if ( plTrimmedPoly.GetPointNbr() == 0) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; return true ; } @@ -3403,20 +3543,37 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, if ( ! AreSamePointApprox( ptToAdd, ptLast)) vDir = ptToAdd - ptLast ; else - return true ; + return false ; // se non riesco a normalizzare perché sono troppo vicino ad un vertice allora aggiungo direttamente il vertice if ( ! vDir.Normalize()) { plTrimmedPoly.EraseLastUPoint() ; - if ( AreSamePointApprox( ptToAdd, ptBr)) - plTrimmedPoly.AddUPoint( c, ptBr) ; - else if ( AreSamePointApprox( ptToAdd, ptTR)) - plTrimmedPoly.AddUPoint( c, ptTR) ; - else if ( AreSamePointApprox( ptToAdd, ptTl)) - plTrimmedPoly.AddUPoint( c, ptTl) ; - else if ( AreSamePointApprox( ptToAdd, ptBL)) - plTrimmedPoly.AddUPoint( c, ptBL) ; + Point3d ptVert ; + int nVert = -1 ; + if ( AreSamePointApprox( ptToAdd, ptBr)){ + ptVert = ptBr ; + nVert = 1 ; + } + else if ( AreSamePointApprox( ptToAdd, ptTR)) { + ptVert = ptTR ; + nVert = 2 ; + } + else if ( AreSamePointApprox( ptToAdd, ptTl)) { + ptVert = ptTl ; + nVert = 3 ; + } + else if ( AreSamePointApprox( ptToAdd, ptBL)) { + ptVert = ptBL ; + nVert = 0 ; + } else - plTrimmedPoly.AddUPoint( c, ptToAdd) ; + ptVert = ptToAdd ; + plTrimmedPoly.AddUPoint( c, ptVert) ; + Point3d pt3d ; + if ( nVert != -1) + pt3d = m_mVert.at(nId)[nVert] ; + else + m_pSrfBz->GetPointD1D2( ptVert.x, ptVert.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; return true ; } @@ -3428,10 +3585,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, Point3d ptIntermed = vEdgeVertex[0][t] ; if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[0][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // edge 1 @@ -3440,10 +3600,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, Point3d ptIntermed = vEdgeVertex[1][t] ; if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[1][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // edge 2 @@ -3452,10 +3615,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, Point3d ptIntermed = vEdgeVertex[2][t] ; if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[2][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // edge 3 @@ -3464,22 +3630,29 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, Point3d ptIntermed = vEdgeVertex[3][t] ; if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[3][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // sono allineato con un lato, ma NON sono su un lato // aggiungo e basta else { plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } } // non su un edge, quindi aggiungo e basta else { plTrimmedPoly.AddUPoint( c, ptToAdd) ; + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } return true ; @@ -3899,13 +4072,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) // recupero i poligoni base delle celle sui bordi POLYLINEMATRIX mPL ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[0], false, vEdges[0]) ; + GetPolygonsBasic( mPL[0], vEdges[0]) ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[1], false, vEdges[1]) ; + GetPolygonsBasic( mPL[1], vEdges[1]) ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[2], false, vEdges[2]) ; + GetPolygonsBasic( mPL[2], vEdges[2]) ; mPL.emplace_back() ; - GetPolygonsBasic( mPL[3], false, vEdges[3]) ; + GetPolygonsBasic( mPL[3], vEdges[3]) ; // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato for ( int i = 0 ; i < int( mPL.size()) ; ++i) { @@ -4097,6 +4270,7 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts) bool Tree::AdjustCuts( void) { + // correzione del verso dei tagli aperti if ( int( m_mTree.at( -1).m_vInters.size()) == 1) return true ; // li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR @@ -4138,10 +4312,19 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons) pl.AddUPoint(2, m_mTree.at(nRoot).GetBottomLeft()) ; pl.AddUPoint(3, m_mTree.at(nRoot).GetBottomRight()) ; pl.Close() ; + PolyLine pl3d ; + pl3d.AddUPoint(0, m_mVert.at(nRoot)[2]) ; + pl3d.AddUPoint(1, m_mVert.at(nRoot)[3]) ; + pl3d.AddUPoint(2, m_mVert.at(nRoot)[0]) ; + pl3d.AddUPoint(3, m_mVert.at(nRoot)[1]) ; + pl3d.Close() ; // ora posso creare il poligono della cella con i tagli + POLYLINEMATRIX vPolygons3d ; while( (int)vToCheck.size() != 0) { int nPolyBefore = nPoly ; - CreateCellPolygons( 0, vPolygons, vToCheck, nPoly, vnParentChunk, pl) ; + CreateCellPolygons( 0, vPolygons, vPolygons3d, vToCheck, nPoly, vnParentChunk, pl, pl3d) ; // l'aggiunta di vPolygons3d forse è un problema in questo punto. + // sarà da valutare quando si aggiungerà la funzione per aggiungere tagli aperti + // e se si vuole usare la funzione su uno spazio 2D ideale non collegato ad una sup di Bezier if ( nPolyBefore == nPoly) break ; } diff --git a/Tree.h b/Tree.h index e5ffece..7559dbf 100644 --- a/Tree.h +++ b/Tree.h @@ -238,10 +238,14 @@ class Tree bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh // dSideMin è lunghezza minima del lato di una cella nello spazio reale bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; - bool GetPolygons( POLYLINEMATRIX& vPolygons) ; - bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bFroTriangulation = false, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero - // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati - // se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico + bool GetPolygons( POLYLINEMATRIX& vvPolygons) ; + bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d) ; + bool GetPolygons( POLYLINEMATRIX& vPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) ; + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero + // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati + // se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygons3d) ; + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle @@ -272,14 +276,14 @@ class Tree bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle bool FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim // resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto - bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni. - bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella + bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni. + bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR. bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3) bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // sul lato nEdge controllo se ptP1 viene prima di ptP2. bool AreSameEdge( int nEdge1, int nEdge2) const ; // indica se i due edge sono lo stesso. Un vertice adiacente ad un edge viene considerato uguale a questo edge - bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto + bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto bool SetRightEdgeIn( int nId) ; // categorizza la cella in base all'edge destro per poter poi definire m_nFlag bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata) bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW) @@ -311,6 +315,7 @@ class Tree int m_nSpanU ; // numero di span lungo il parametro U int m_nSpanV ; // numero di span lungo il parametro V POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree + POLYLINEMATRIX m_vPolygons3d ; // matrice dei poligoni3d del tree std::map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root std::map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01 INTVECTOR m_vnLeaves ; // vettore delle foglie From 9a16259ff59a42e7203afc87d16dddc20d4f96ef Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 20 Jun 2024 12:52:03 +0200 Subject: [PATCH 33/45] EgtGeomKernel : - correzione al miglioramento sul tempo di triangolazione delle bezier. --- Tree.cpp | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 227a65f..69ab52a 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -2956,8 +2956,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ; vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ; // la PolyLine è riempita a partire dal lato bottom - Point3d ptStart ; + Point3d ptStart, pt3d ; plCell.GetFirstPoint( ptStart) ; + plCell3d.GetFirstPoint( pt3d) ; INTVECTOR vEdge = { 2, 3, 0, 1} ; for ( int p = 0 ; p < 4 ; ++ p) { int j = vEdge[p] ; @@ -2965,8 +2966,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX if ( j == 3) next = 0 ; Point3d ptToAdd ; - while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, vEdgeVertex[next][0])) { + while ( plCell.GetNextPoint( ptToAdd) && plCell3d.GetNextPoint( pt3d) && ! AreSamePointExact( ptToAdd, vEdgeVertex[next][0])) { vEdgeVertex[j].push_back( ptToAdd) ; + vEdgeVertex3d[j].push_back( pt3d) ; } } @@ -3581,7 +3583,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe // se su un edge devo fare dei controlli // edge 0 if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptTR.y && abs( vDir.x) > 1 - EPS_SMALL) { - for ( int t = 0 ; t < (int)vEdgeVertex[0].size() ; ++ t) { + for ( int t = 1 ; t < (int)vEdgeVertex[0].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[0][t] ; if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3590,13 +3592,17 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[1][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[1][0] ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // edge 1 else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptBL.x && abs( vDir.y) > 1 - EPS_SMALL) { - for ( int t = 0 ; t < (int)vEdgeVertex[1].size() ; ++ t) { + for ( int t = 1 ; t < (int)vEdgeVertex[1].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[1][t] ; if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3605,13 +3611,17 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[2][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[2][0] ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // edge 2 else if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptBL.y && abs( vDir.x) > 1 - EPS_SMALL) { - for ( int t = 0 ; t < (int)vEdgeVertex[2].size() ; ++ t) { + for ( int t = 1 ; t < (int)vEdgeVertex[2].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[2][t] ; if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3620,13 +3630,17 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[3][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[3][0] ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } // edge 3 else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptTR.x && abs( vDir.y) > 1 - EPS_SMALL) { - for ( int t = 0 ; t < (int)vEdgeVertex[3].size() ; ++ t) { + for ( int t = 1 ; t < (int)vEdgeVertex[3].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[3][t] ; if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3635,7 +3649,11 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[0][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[0][0] ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; ++ c ; } From d67cca385ef949d4e8eadcd44a45c5321a8e4048 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 3 Jul 2024 11:15:10 +0200 Subject: [PATCH 34/45] EgtGeomKernel : - correzioni alle rigate con le Bezier. --- SurfBezier.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 089ec0e..eabbce0 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3875,7 +3875,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int if ( ( plU1.IsClosed() && plU1.GetPointNbr() < 3) || plU1.GetPointNbr() < 2) return false ; - // determino il numero di span che avrà lòa superficie basandomi sulla curva con più sottocurve + // determino il numero di span che avrà la superficie basandomi sulla curva con più sottocurve int nSpanU = max( nSpanU0, nSpanU1) ; // punti per curva int nLastPoint = nDegU + 1 ; @@ -3886,8 +3886,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // se sto usando la ISOPARM o la MINDIST semplice allora collego più span di una curva allo stesso punto // ( aggiungo virtualmente delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) if ( nRuledType != RLT_B_MINDIST_PLUS){ - // inizializzo la superficie - Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; if ( nRuledType == RLT_B_MINDIST) { // creo le liste di punti per le isoparametriche in U PNTIVECTOR vPnt0Match, vPnt1Match ; @@ -3904,8 +3902,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int if ( nIndMatch != nIndMatchNext) nRep0 += nIndMatchNext - nIndMatch - 1; } + int nRep1 = int( vPnt1Match.size() - 1) - vPnt0Match.back().second ; // reinizializzo la superficie con il nuovo numero di span in U - nSpanU = nSpanU0 + nRep0 ; + nSpanU = nSpanU0 + nRep0 + nRep1 ; + if ( nSpanU < max(nSpanU0, nSpanU1)) + nSpanU = max(nSpanU0, nSpanU1) ; nSecondRowInd = nDegU * nSpanU + 1 ; Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; @@ -3942,7 +3943,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } else { // ripeto l'ultimo punto aggiunto per il numero di curve balzate della seconda curva - 1 - // aggiungo una sottocurva dalla prima curva for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i != 0 ? i - 1 : i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { @@ -3979,6 +3979,40 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } + //controllo se ho aggiunto tutti i punti della seconda curva + if ( vPnt0Match.back().second != nSpanU1) { + // riaggiungo l'ultimo punto + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSpanU0 - 1)) ; + int nPoint = nDegU ; + while( nCount0 - 1 < nSpanU1) { + for ( int j = 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; + } + ++ nCount0 ; + } + + // aggiungo le restanti sottocurve della curva 2 + int nCrv1 = vPnt0Match.back().second ; + while( nCrv1 < nSpanU1) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv1)) ; + for ( int j = 1 ; j < nLastPoint ; ++j) { + if ( ! bRat1) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; + } + ++ nCount1 ; + ++ nCrv1 ; + } + } + + + + + ////////////////// ORA SI PUò CANCELLARE //// // QUESTO PEZZO E' DA SISTEMARE //// controllo di aver aggiunto anche gli ultimi punti //int nInd = nIndMatchNext < nSpanU0 ? nIndMatchNext : nIndMatchNext - 1 ; @@ -4043,6 +4077,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } if ( nRuledType == RLT_B_ISOPAR) { + // inizializzo la superficie + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; Point3d ptP0Start ; pCrvU0->GetStartPoint( ptP0Start) ; Point3d ptP1Start ; pCrvU1->GetStartPoint( ptP1Start) ; // setto i primi due punti delle righe @@ -4167,6 +4203,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nAtStart1 = 0 ; int nAtEnd1 = 0 ; Point3d ptP0 ; plU0.GetFirstPoint( ptP0) ; + int c = 0 ; // debug + int nCrvCount = 0 ; while ( plU0.GetNextPoint( ptP0, true)) { // devo salvarmi se matcho più punti con lo start o l'end della curva totale DistPointCurve dpc( ptP0, *pCrvU1, false) ; @@ -4181,13 +4219,18 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int continue ; } Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; // devo verificare se ho già un punto di start/end nelle vicinanze + nCrvCount = pCrvU1->GetCurveCount() ; //debug pCrvU1->AddJoint( dParam) ; + if( nCrvCount == pCrvU1->GetCurveCount())//debug + int a = 0 ; //debug nSpanU1 = pCrvU1->GetCurveCount() ; // devo aggiungere un controllo in modo che i parametri trovati siano sempre crescenti + ++c ;// debug } int nAtStart0 = 0 ; int nAtEnd0 = 0 ; Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; + c = 0 ;// debug while ( plU1.GetNextPoint( ptP1, true)) { DistPointCurve dpc( ptP1, *pCrvU0, false) ; int nFlag = 0 ; @@ -4201,16 +4244,24 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int continue ; } Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; // devo verificare se ho già un punto di start/end nelle vicinanze + nCrvCount = pCrvU0->GetCurveCount() ; // debug pCrvU0->AddJoint( dParam) ; + if( nCrvCount == pCrvU0->GetCurveCount()) + int a = 0 ; nSpanU0 = pCrvU0->GetCurveCount() ; + ++c ;// debug } nSpanU = max( nSpanU0, nSpanU1) ; - // se la differenza tra il numero di span delle due curve non è colmata dalla ripetizione dello start o dello'end allora devo tenere conto anche - // delle addJoint che non hanno fatto nulla ( perché chieste di splittare la curva troppo vicino ad un punto già esistente di split, magari in un caso anche di multimatch per lo stesso punto) - if ( (nSpanU0 > nSpanU1 && nSpanU0 != nSpanU1 + nAtStart1 + nAtEnd1) || - (nSpanU0 < nSpanU1 && nSpanU1 != nSpanU0 + nAtStart0 + nAtEnd0)) - return false ; + + // questo controllo SERVE??? è da cambiare per tenere dentro anche il caso di mismatch?? + //// se la differenza tra il numero di span delle due curve non è colmata dalla ripetizione dello start o dell'end allora devo tenere conto anche + //// delle addJoint che non hanno fatto nulla ( perché chieste di splittare la curva troppo vicino ad un punto già esistente di split, magari in un caso anche di multimatch per lo stesso punto) + //if ( (nSpanU0 > nSpanU1 && nSpanU0 != nSpanU1 + nAtStart1 + nAtEnd1) || + // (nSpanU0 < nSpanU1 && nSpanU1 != nSpanU0 + nAtStart0 + nAtEnd0)) + // return false ; + + nSecondRowInd = nDegU * nSpanU + 1 ; // inizializzo la superficie Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; From b4878f1ac0e274b90c93cd0f4eca51cde2bcf95b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 5 Jul 2024 17:12:08 +0200 Subject: [PATCH 35/45] EgtGeomKernel : - correzioni e migliorie alle rigate con le bezier MINDISTPLUS. --- SurfBezier.cpp | 350 ++++++++++++++++++++++++++++++------------------- 1 file changed, 217 insertions(+), 133 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index eabbce0..5715718 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3910,7 +3910,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nSecondRowInd = nDegU * nSpanU + 1 ; Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; - // come riferimento tengo i match identificati dalla curva 0 + // numero di span aggiunte su U0 e U1 nCount0 = 0 ; nCount1 = 0 ; @@ -3942,11 +3942,28 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++nCount1 ; } else { + // qui devo capire se aggiungere la nuova sottocurva prima o dopo la ripetizione dei punti + // se il match del punto della seconda curva è uguale al punto a cui ero arrivato sulla prima curva allora prima aggiungo la ripetizione di punti + // se invece il match è più avanti allora aggiuno prima la curva e poi la ripetzione di punti + bool bSubCurveAddedFirst = false ; + if ( vPnt1Match[vPnt0Match[i+1].second].second != i+1 ) { + bSubCurveAddedFirst = true ; + // aggiungo una sottocurva dalla prima curva + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + } + ++ nCount0 ; + } + // ripeto l'ultimo punto aggiunto per il numero di curve balzate della seconda curva - 1 for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i != 0 ? i - 1 : i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - int nPoint = nCount0 == 0 ? 0 : nDegU ; + int nPoint = nCount0 == 0 && ! bSubCurveAddedFirst ? 0 : nDegU ; if ( ! bRat0) SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; else @@ -3954,15 +3971,18 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } ++ nCount0 ; } - // aggiungo una sottocurva dalla prima curva - pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; - for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + // se non l'ho già aggiunta prima aggiungo una sottocurva della prima curva + if( ! bSubCurveAddedFirst) { + // aggiungo una sottocurva dalla prima curva + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + } + ++ nCount0 ; } - ++ nCount0 ; // aggiungo tutte le sottocurve che ho balzato della seconda @@ -4008,72 +4028,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nCrv1 ; } } - - - - - ////////////////// ORA SI PUò CANCELLARE - //// // QUESTO PEZZO E' DA SISTEMARE - //// controllo di aver aggiunto anche gli ultimi punti - //int nInd = nIndMatchNext < nSpanU0 ? nIndMatchNext : nIndMatchNext - 1 ; - //while ( nCount0 < nSpanU) { - // const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nInd)) ; - // for ( int j = 1 ; j < nLastPoint ; ++j) { - // int nPoint = nInd < nSpanU0 - 1 ? j : nDegU ; - // if ( ! bRat0) - // SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; - // else - // SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; - // } - // ++ nCount0 ; - // if ( nInd < nSpanU0 - 1) - // ++ nInd ; - //} - - //for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { - // nIndMatch = vPnt0Match[i].second ; - // nIndMatchNext = vPnt0Match[i+1].second ; - // if ( nIndMatch == nSpanU1) - // break ; - // const ICurveBezier* pSubCrv1 ; - // if ( nIndMatch == nIndMatchNext) { - // pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch)) ; - // for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - // if( ! bRat1) - // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0)) ; - // else - // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( 0), pSubCrv1->GetControlWeight( 0)) ; - // } - // ++ nCount1 ; - // } - // else { - // for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { - // pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; - // for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - // if( ! bRat1) - // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; - // else - // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; - // } - // ++ nCount1 ; - // } - // } - //} - //// controllo di aver aggiunto anche gli ultimi punti - //nInd = nIndMatchNext < nSpanU1 ? nIndMatchNext : nIndMatchNext - 1 ; - //while ( nCount1 < nSpanU) { - // const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; - // for ( int j = 1 ; j < nLastPoint ; ++j) { - // int nPoint = nInd < nSpanU1 - 1 ? j : nDegU ; - // if( ! bRat1) - // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint)) ; - // else - // SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( nPoint), pSubCrv1->GetControlWeight( nPoint)) ; - // } - // ++ nCount1 ; - // if ( nInd < nSpanU1 - 1) - // ++ nInd ; - //} } if ( nRuledType == RLT_B_ISOPAR) { @@ -4200,111 +4154,241 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva // in quel punto la curva verrà spezzata, a meno che non si trovi una joint già sufficientemente vicina - int nAtStart1 = 0 ; + // prima trovo le associazioni senza aggiunte di punti + PNTIVECTOR vPnt0Match, vPnt1Match ; + bool bCommonPoint = false ; + AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; + + int nAtStart1 = 0 ; // match ripetuti dalla curva U0 allo start della curva U1 int nAtEnd1 = 0 ; Point3d ptP0 ; plU0.GetFirstPoint( ptP0) ; - int c = 0 ; // debug + int c = 0 ; int nCrvCount = 0 ; + int nRep0 = 0 ; // match interni consecutivi uguali di punti della curva U0 con punti della curva U1 + int nRep1 = 0 ; + double dLastParamMatch = 0 ; + Point3d ptLastPointMatch = ptP0 ; + BOOLVECTOR vbRep0( nSpanU0) ; + INTVECTOR vnAddedOrNextIsRep0 ; // 0 non Rep, 1 Rep, 2 Next is Rep ; + DBLVECTOR vdSplit0 ; + fill( vbRep0.begin(), vbRep0.end(), false) ; while ( plU0.GetNextPoint( ptP0, true)) { // devo salvarmi se matcho più punti con lo start o l'end della curva totale DistPointCurve dpc( ptP0, *pCrvU1, false) ; int nFlag = 0 ; double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; if ( dParam < EPS_SMALL ) { ++nAtStart1 ; + vbRep0[c] = true ; + ++c ; continue ; } else if ( dParam > nSpanU1 + EPS_SMALL ) { ++ nAtEnd1 ; + vbRep0[c] = true ; + ++c ; continue ; } - Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; // devo verificare se ho già un punto di start/end nelle vicinanze - nCrvCount = pCrvU1->GetCurveCount() ; //debug - pCrvU1->AddJoint( dParam) ; - if( nCrvCount == pCrvU1->GetCurveCount())//debug - int a = 0 ; //debug - nSpanU1 = pCrvU1->GetCurveCount() ; - // devo aggiungere un controllo in modo che i parametri trovati siano sempre crescenti - ++c ;// debug + if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) { + dParam = dLastParamMatch ; + vbRep0[c] = true ; + ++ nRep0 ; + ++c ; + continue ; + } + else { + dLastParamMatch = dParam ; + ptLastPointMatch = ptJoint ; + nCrvCount = pCrvU1->GetCurveCount() ; + //pCrvU1->AddJoint( dParam) ; + + // se sono già troppo vicino ad un split esistente allora non faccio nulla + if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM) { + ++c ; + continue ; + } + vdSplit0.push_back( dParam) ; + // verifico se ho un match per questo punto + // in tal caso vuol dire che sto creando una ripetizione nRep1 + int nCase = 0 ; + for ( int j = 0 ; j < int( vPnt1Match.size()) ; ++j) { + if ( vPnt1Match[j].second == c + 1) { + ++nRep1 ; + // capisco se il punto è rep o se lo è il suo successivo + if( j < dParam) + nCase = 1 ; + else + nCase = 2 ; + break ; + } + } + vnAddedOrNextIsRep0.push_back( nCase) ; + } + + //nSpanU1 = pCrvU1->GetCurveCount() ; + ++c ; } int nAtStart0 = 0 ; int nAtEnd0 = 0 ; Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; - c = 0 ;// debug + c = 0 ; + dLastParamMatch = 0 ; + ptLastPointMatch = ptP1 ; + INTVECTOR vnAddedOrNextIsRep1 ; // 0 non Rep, 1 Rep, 2 Next is Rep ; + DBLVECTOR vdSplit1 ; + BOOLVECTOR vbRep1( plU1.GetPointNbr() - 1) ; + fill( vbRep1.begin(), vbRep1.end(), false) ; + bool bPrevWasRep = false ; while ( plU1.GetNextPoint( ptP1, true)) { DistPointCurve dpc( ptP1, *pCrvU0, false) ; int nFlag = 0 ; double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; if ( dParam < EPS_SMALL ) { ++nAtStart0 ; + vbRep1[c] = true ; + ++c ; continue ; } else if ( dParam > nSpanU0 - EPS_SMALL ) { ++ nAtEnd0 ; + vbRep1[c] = true ; + ++c ; continue ; } - Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; // devo verificare se ho già un punto di start/end nelle vicinanze - nCrvCount = pCrvU0->GetCurveCount() ; // debug - pCrvU0->AddJoint( dParam) ; - if( nCrvCount == pCrvU0->GetCurveCount()) - int a = 0 ; - nSpanU0 = pCrvU0->GetCurveCount() ; - ++c ;// debug + if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) { + dParam = dLastParamMatch ; + vbRep1[c] = true ; + ++ nRep1 ; + ++c ; + continue ; + } + else { + dLastParamMatch = dParam ; + ptLastPointMatch = ptJoint ; + nCrvCount = pCrvU0->GetCurveCount() ; + //pCrvU0->AddJoint( dParam) ; + //// se ho aggiunto un nuovo punto alla curva U0 allora devo allungare coerentemente il vettore vbRep0 + //if( nCrvCount != pCrvU0->GetCurveCount()) + // vbRep0.insert( vbRep0.begin() + int(round( dParam - 0.5)), false) ; + + //se sono troppo vicino ad uno split esistente allora non faccio nulla + if( abs(dParam - round( dParam)) < 100 * EPS_PARAM) { + ++c ; + continue ; + } + vdSplit1.push_back( dParam) ; + // verifico se ho un match per questo punto + // in tal caso vuol dire che sto creando una ripetizione nRep1 + int nCase = 0 ; + for ( int j = 0 ; j < int( vPnt0Match.size()) ; ++j) { + if ( vPnt0Match[j].second == c + 1) { + ++nRep0 ; + // capisco se il punto è rep o se lo è il suo successivo + if( j < dParam) + nCase = 1 ; + else + nCase = 2 ; + break ; + } + } + vnAddedOrNextIsRep1.push_back( nCase) ; + } + + //nSpanU0 = pCrvU0->GetCurveCount() ; + ++c ; } - nSpanU = max( nSpanU0, nSpanU1) ; + + //// correggo il vettore vbRep1 aggiungendo gli elementi corrispondenti ai punti che ho aggiunto + //plU1.GetFirstPoint( ptP1) ; + //bool bAdvance = true ; + //for ( int i = 0 ; i < int( pCrvU1->GetCurveCount()) ; ++i) { + // if ( bAdvance) + // plU1.GetNextPoint( ptP1) ; + // const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( i)) ; + // Point3d ptSubEnd ; pSubCrv1->GetEndPoint( ptSubEnd) ; + // if ( ! AreSamePointApprox( ptP1, ptSubEnd)) { + // vbRep1.insert( vbRep1.begin() + i, false) ; + // bAdvance = false ; + // } + // else + // bAdvance = true ; + //} - // questo controllo SERVE??? è da cambiare per tenere dentro anche il caso di mismatch?? - //// se la differenza tra il numero di span delle due curve non è colmata dalla ripetizione dello start o dell'end allora devo tenere conto anche - //// delle addJoint che non hanno fatto nulla ( perché chieste di splittare la curva troppo vicino ad un punto già esistente di split, magari in un caso anche di multimatch per lo stesso punto) - //if ( (nSpanU0 > nSpanU1 && nSpanU0 != nSpanU1 + nAtStart1 + nAtEnd1) || - // (nSpanU0 < nSpanU1 && nSpanU1 != nSpanU0 + nAtStart0 + nAtEnd0)) - // return false ; + // applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep + for ( int z = int( vdSplit0.size() - 1) ; z >= 0 ; --z) { + double dSplit = vdSplit0[z] ; + pCrvU1->AddJoint( dSplit) ; + int nSplit = int( dSplit) ; + switch( vnAddedOrNextIsRep0[z]) { + case 0 : vbRep1.insert( vbRep1.begin() + nSplit, false) ; break ; + case 1 : vbRep1.insert( vbRep1.begin() + nSplit, true) ; break ; + case 2 : vbRep1[nSplit] = true ; + vbRep1.insert( vbRep1.begin() + nSplit, false) ; break ; + } + } + for ( int z = int( vdSplit1.size() - 1) ; z >= 0 ; --z) { + double dSplit = vdSplit1[z] ; + pCrvU0->AddJoint( dSplit) ; + int nSplit = int( dSplit) ; + switch( vnAddedOrNextIsRep1[z]) { + case 0 : vbRep0.insert( vbRep0.begin() + nSplit, false) ; break ; + case 1 : vbRep0.insert( vbRep0.begin() + nSplit, true) ; break ; + case 2 : vbRep0[nSplit] = true ; + vbRep0.insert( vbRep0.begin() + nSplit, false) ; break ; + } + } + nSpanU0 = pCrvU0->GetCurveCount() ; + nSpanU1 = pCrvU1->GetCurveCount() ; + // trovo il numero di span che dovrà avere la superficie + // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) + nSpanU = nSpanU0 + nAtStart0 + nAtEnd0 + nRep1 ; + nSecondRowInd = nDegU * nSpanU + 1 ; // inizializzo la superficie Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; - // costruisco la matrice dei punti di controllo aggiungendo i punti delle due curve appena modificate - for ( int j = 0 ; j < nSpanU ; ++j) { - //int nCrv = nAtStart0 != 0 ? j - ( nAtStart0 - 1) : j ; - int nCrv = j - nAtStart0 ; - if ( j < nAtStart0) - nCrv = 0 ; - else if ( j >= nSpanU - 1 - nAtEnd0) - nCrv = nSpanU0 -1 ; - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCrv)) ; - for( int i = j == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + + // aggiungo i punti di controllo scorrendo in contemporanea le due curve + int nAddedSpan = 0 ; + int nCrv0 = 0 ; + int nCrv1 = 0 ; + while ( nAddedSpan < nSpanU) { + if ( nCrv0 >= nSpanU0) + nCrv0 = nSpanU0 - 1; + if ( nCrv1 >= nSpanU1) + nCrv1 = nSpanU1 - 1; + bool bRep0 = vbRep0[nCrv0] ; + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCrv0)) ; + for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; - if ( j < nAtStart0) - nInd = 0 ; - //else if ( j >= nSpanU - 1 - nAtEnd0 && ((nAtStart0 != 0 ? j - ( nAtStart0 - 1) : j) != nSpanU0 - 1)) - else if ( j >= nSpanU - 1 - nAtEnd0 && j - nAtStart0 != nSpanU0 - 1) - nInd = nDegU ; + // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 + if ( vbRep1[nCrv1]) + nInd = nCrv0 < nSpanU0 ? 0 : nDegU ; if ( ! bRat) - SetControlPoint( j * nDegU + i, pSubCrv0->GetControlPoint( nInd)) ; + SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd)) ; else - SetControlPoint( j * nDegU + i, pSubCrv0->GetControlPoint( nInd), pSubCrv0->GetControlWeight( nInd)) ; + SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd), pSubCrv0->GetControlWeight( nInd)) ; } - } - for ( int j = 0 ; j < nSpanU ; ++j) { - int nCrv = j - nAtStart1 ; - if ( j < nAtStart1) - nCrv = 0 ; - else if ( j >= nSpanU - 1 - nAtEnd1) - nCrv = nSpanU1 -1 ; - const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv)) ; - for( int i = j == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + if ( ! vbRep1[nCrv1]) + ++ nCrv0 ; + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv1)) ; + for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; - if ( j < nAtStart1) - nInd = 0 ; - else if ( j >= nSpanU - 1 - nAtEnd1 && j - nAtStart1 != nSpanU1 - 1) - nInd = nDegU ; + // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 + if ( bRep0) + nInd = nCrv1 < nSpanU1 ? 0 : nDegU ; if ( ! bRat) - SetControlPoint( nSecondRowInd + j * nDegU + i, pSubCrv1->GetControlPoint( nInd)) ; + SetControlPoint( nSecondRowInd + nAddedSpan * nDegU + i, pSubCrv1->GetControlPoint( nInd)) ; else - SetControlPoint( nSecondRowInd + j * nDegU + i, pSubCrv1->GetControlPoint( nInd), pSubCrv1->GetControlWeight( nInd)) ; + SetControlPoint( nSecondRowInd + nAddedSpan * nDegU + i, pSubCrv1->GetControlPoint( nInd), pSubCrv1->GetControlWeight( nInd)) ; } + if ( ! bRep0) + ++ nCrv1 ; + ++ nAddedSpan ; } } From 7a66ad27d83585728d0afb23dc34d78a54941e71 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 8 Jul 2024 15:20:09 +0200 Subject: [PATCH 36/45] EgtGeomKernel : - correzioni alle rigate con le bezier. --- SurfBezier.cpp | 66 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 5715718..301b1fc 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -4155,9 +4155,15 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // in quel punto la curva verrà spezzata, a meno che non si trovi una joint già sufficientemente vicina // prima trovo le associazioni senza aggiunte di punti - PNTIVECTOR vPnt0Match, vPnt1Match ; - bool bCommonPoint = false ; - AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; + Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; + vector> vMatch1 ; + while ( plU1.GetNextPoint( ptP1, true)) { + DistPointCurve dpc( ptP1, *pCrvU0, false) ; + int nFlag = 0 ; + double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; + vMatch1.push_back( pair( ptJoint, dParam)) ; + } int nAtStart1 = 0 ; // match ripetuti dalla curva U0 allo start della curva U1 int nAtEnd1 = 0 ; @@ -4171,6 +4177,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int BOOLVECTOR vbRep0( nSpanU0) ; INTVECTOR vnAddedOrNextIsRep0 ; // 0 non Rep, 1 Rep, 2 Next is Rep ; DBLVECTOR vdSplit0 ; + DBLVECTOR vdMatch0 ; fill( vbRep0.begin(), vbRep0.end(), false) ; while ( plU0.GetNextPoint( ptP0, true)) { // devo salvarmi se matcho più punti con lo start o l'end della curva totale @@ -4178,6 +4185,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nFlag = 0 ; double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; + vdMatch0.push_back( dParam) ; if ( dParam < EPS_SMALL ) { ++nAtStart1 ; vbRep0[c] = true ; @@ -4185,8 +4193,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int continue ; } else if ( dParam > nSpanU1 + EPS_SMALL ) { + vbRep0[c] = nAtEnd1 == 0 ? false : true ; + vbRep0.back() = true ; ++ nAtEnd1 ; - vbRep0[c] = true ; ++c ; continue ; } @@ -4212,11 +4221,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // verifico se ho un match per questo punto // in tal caso vuol dire che sto creando una ripetizione nRep1 int nCase = 0 ; - for ( int j = 0 ; j < int( vPnt1Match.size()) ; ++j) { - if ( vPnt1Match[j].second == c + 1) { + for ( int j = 0 ; j < int( vMatch1.size()) ; ++j) { + if ( abs(vMatch1[j].second - (c + 1)) < EPS_SMALL) { ++nRep1 ; // capisco se il punto è rep o se lo è il suo successivo - if( j < dParam) + if( j + 1 < dParam) nCase = 1 ; else nCase = 2 ; @@ -4231,7 +4240,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } int nAtStart0 = 0 ; int nAtEnd0 = 0 ; - Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; + /*Point3d ptP1 ;*/ plU1.GetFirstPoint( ptP1) ; c = 0 ; dLastParamMatch = 0 ; ptLastPointMatch = ptP1 ; @@ -4252,8 +4261,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int continue ; } else if ( dParam > nSpanU0 - EPS_SMALL ) { + vbRep1[c] = nAtEnd0 == 0 ? false : true ; + vbRep1.back() = true ; ++ nAtEnd0 ; - vbRep1[c] = true ; ++c ; continue ; } @@ -4282,11 +4292,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // verifico se ho un match per questo punto // in tal caso vuol dire che sto creando una ripetizione nRep1 int nCase = 0 ; - for ( int j = 0 ; j < int( vPnt0Match.size()) ; ++j) { - if ( vPnt0Match[j].second == c + 1) { + for ( int j = 0 ; j < int( vdMatch0.size()) ; ++j) { + if ( abs(vdMatch0[j] - (c + 1)) < EPS_SMALL) { ++nRep0 ; // capisco se il punto è rep o se lo è il suo successivo - if( j < dParam) + if( j + 1 < dParam) nCase = 1 ; else nCase = 2 ; @@ -4318,10 +4328,17 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep + int nUnit = int( vdSplit0.back()) ; for ( int z = int( vdSplit0.size() - 1) ; z >= 0 ; --z) { double dSplit = vdSplit0[z] ; - pCrvU1->AddJoint( dSplit) ; int nSplit = int( dSplit) ; + // se sto cercando di fare uno split sulla stessa curva che ho già splittato al passaggio precedente allora devo + // riscalare + if ( nSplit == nUnit && z < int( vdSplit0.size() - 1)) { + dSplit = nSplit + ( dSplit - nSplit) / (vdSplit0[z+1] - nSplit); + } + nUnit = nSplit ; + pCrvU1->AddJoint( dSplit) ; switch( vnAddedOrNextIsRep0[z]) { case 0 : vbRep1.insert( vbRep1.begin() + nSplit, false) ; break ; case 1 : vbRep1.insert( vbRep1.begin() + nSplit, true) ; break ; @@ -4329,10 +4346,17 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int vbRep1.insert( vbRep1.begin() + nSplit, false) ; break ; } } + nUnit = int( vdSplit1.back()) ; for ( int z = int( vdSplit1.size() - 1) ; z >= 0 ; --z) { double dSplit = vdSplit1[z] ; - pCrvU0->AddJoint( dSplit) ; int nSplit = int( dSplit) ; + // se sto cercando di fare uno split sulla stessa curva che ho già splittato al passaggio precedente allora devo + // riscalare + if ( nSplit == nUnit && z < int( vdSplit1.size() - 1)) { + dSplit = nSplit + ( dSplit - nSplit) / (vdSplit1[z+1] - nSplit); + } + nUnit = nSplit ; + pCrvU0->AddJoint( dSplit) ; switch( vnAddedOrNextIsRep1[z]) { case 0 : vbRep0.insert( vbRep0.begin() + nSplit, false) ; break ; case 1 : vbRep0.insert( vbRep0.begin() + nSplit, true) ; break ; @@ -4356,18 +4380,24 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nAddedSpan = 0 ; int nCrv0 = 0 ; int nCrv1 = 0 ; + bool bLast0 = false ; + bool bLast1 = false ; while ( nAddedSpan < nSpanU) { - if ( nCrv0 >= nSpanU0) + if ( nCrv0 >= nSpanU0){ nCrv0 = nSpanU0 - 1; - if ( nCrv1 >= nSpanU1) + bLast0 = true ; + } + if ( nCrv1 >= nSpanU1) { nCrv1 = nSpanU1 - 1; + bLast1 = true ; + } bool bRep0 = vbRep0[nCrv0] ; const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCrv0)) ; for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 if ( vbRep1[nCrv1]) - nInd = nCrv0 < nSpanU0 ? 0 : nDegU ; + nInd = ! bLast0 ? 0 : nDegU ; if ( ! bRat) SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd)) ; else @@ -4380,7 +4410,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nInd = i ; // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 if ( bRep0) - nInd = nCrv1 < nSpanU1 ? 0 : nDegU ; + nInd = ! bLast1 ? 0 : nDegU ; if ( ! bRat) SetControlPoint( nSecondRowInd + nAddedSpan * nDegU + i, pSubCrv1->GetControlPoint( nInd)) ; else From bc3c1e377e8a8b9201a8d13f804a4cf2941529a5 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 9 Jul 2024 13:04:48 +0200 Subject: [PATCH 37/45] =?UTF-8?q?EgtGeomKernel=20:=20-=20corretta=20la=20r?= =?UTF-8?q?uled=20con=20bezier=20in=20modalit=C3=A0=20MinDistPlus.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 149 ++++++++++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 58 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 301b1fc..d145113 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3943,7 +3943,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } else { // qui devo capire se aggiungere la nuova sottocurva prima o dopo la ripetizione dei punti - // se il match del punto della seconda curva è uguale al punto a cui ero arrivato sulla prima curva allora prima aggiungo la ripetizione di punti + // se il match del punto della U1 è uguale al punto a cui ero arrivato sulla U0 allora prima aggiungo la ripetizione di punti // se invece il match è più avanti allora aggiuno prima la curva e poi la ripetzione di punti bool bSubCurveAddedFirst = false ; if ( vPnt1Match[vPnt0Match[i+1].second].second != i+1 ) { @@ -4192,7 +4192,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++c ; continue ; } - else if ( dParam > nSpanU1 + EPS_SMALL ) { + else if ( dParam > nSpanU1 - EPS_SMALL ) { vbRep0[c] = nAtEnd1 == 0 ? false : true ; vbRep0.back() = true ; ++ nAtEnd1 ; @@ -4210,8 +4210,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch = dParam ; ptLastPointMatch = ptJoint ; nCrvCount = pCrvU1->GetCurveCount() ; - //pCrvU1->AddJoint( dParam) ; - // se sono già troppo vicino ad un split esistente allora non faccio nulla if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM) { ++c ; @@ -4223,24 +4221,33 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nCase = 0 ; for ( int j = 0 ; j < int( vMatch1.size()) ; ++j) { if ( abs(vMatch1[j].second - (c + 1)) < EPS_SMALL) { - ++nRep1 ; - // capisco se il punto è rep o se lo è il suo successivo - if( j + 1 < dParam) - nCase = 1 ; - else - nCase = 2 ; + // devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione + bool bFoundMatch = false ; + for ( int z = int( vMatch1[j].second) ; z < int( vdMatch0.size()) ; ++z) { + if ( abs( vdMatch0[z] - ( j + 1 )) < EPS_SMALL ) { + bFoundMatch = true ; + break ; + } + } + + if ( ! bFoundMatch) { + ++nRep1 ; + // capisco se il punto è rep o se lo è il suo successivo + if( j + 1 < dParam) + nCase = 1 ; + else + nCase = 2 ; + } break ; } } vnAddedOrNextIsRep0.push_back( nCase) ; } - - //nSpanU1 = pCrvU1->GetCurveCount() ; ++c ; } int nAtStart0 = 0 ; int nAtEnd0 = 0 ; - /*Point3d ptP1 ;*/ plU1.GetFirstPoint( ptP1) ; + plU1.GetFirstPoint( ptP1) ; c = 0 ; dLastParamMatch = 0 ; ptLastPointMatch = ptP1 ; @@ -4248,7 +4255,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int DBLVECTOR vdSplit1 ; BOOLVECTOR vbRep1( plU1.GetPointNbr() - 1) ; fill( vbRep1.begin(), vbRep1.end(), false) ; - bool bPrevWasRep = false ; while ( plU1.GetNextPoint( ptP1, true)) { DistPointCurve dpc( ptP1, *pCrvU0, false) ; int nFlag = 0 ; @@ -4278,11 +4284,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch = dParam ; ptLastPointMatch = ptJoint ; nCrvCount = pCrvU0->GetCurveCount() ; - //pCrvU0->AddJoint( dParam) ; - //// se ho aggiunto un nuovo punto alla curva U0 allora devo allungare coerentemente il vettore vbRep0 - //if( nCrvCount != pCrvU0->GetCurveCount()) - // vbRep0.insert( vbRep0.begin() + int(round( dParam - 0.5)), false) ; - //se sono troppo vicino ad uno split esistente allora non faccio nulla if( abs(dParam - round( dParam)) < 100 * EPS_PARAM) { ++c ; @@ -4290,45 +4291,39 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } vdSplit1.push_back( dParam) ; // verifico se ho un match per questo punto - // in tal caso vuol dire che sto creando una ripetizione nRep1 + // in tal caso vuol dire che sto creando una ripetizione nRep0 int nCase = 0 ; for ( int j = 0 ; j < int( vdMatch0.size()) ; ++j) { if ( abs(vdMatch0[j] - (c + 1)) < EPS_SMALL) { - ++nRep0 ; - // capisco se il punto è rep o se lo è il suo successivo - if( j + 1 < dParam) - nCase = 1 ; - else - nCase = 2 ; + // devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione + bool bFoundMatch = false ; + for ( int z = int( vdMatch0[j]) ; z < int( vMatch1.size()) ; ++z) { + if ( abs( vMatch1[z].second - ( j + 1 )) < EPS_SMALL ) { + bFoundMatch = true ; + break ; + } + } + + if ( ! bFoundMatch) { + ++nRep0 ; + // capisco se il punto è rep o se lo è il suo successivo + if( j + 1 < dParam) + nCase = 1 ; + else + nCase = 2 ; + } break ; } } vnAddedOrNextIsRep1.push_back( nCase) ; } - - //nSpanU0 = pCrvU0->GetCurveCount() ; ++c ; } - //// correggo il vettore vbRep1 aggiungendo gli elementi corrispondenti ai punti che ho aggiunto - //plU1.GetFirstPoint( ptP1) ; - //bool bAdvance = true ; - //for ( int i = 0 ; i < int( pCrvU1->GetCurveCount()) ; ++i) { - // if ( bAdvance) - // plU1.GetNextPoint( ptP1) ; - // const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( i)) ; - // Point3d ptSubEnd ; pSubCrv1->GetEndPoint( ptSubEnd) ; - // if ( ! AreSamePointApprox( ptP1, ptSubEnd)) { - // vbRep1.insert( vbRep1.begin() + i, false) ; - // bAdvance = false ; - // } - // else - // bAdvance = true ; - //} - - // applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep - int nUnit = int( vdSplit0.back()) ; + int nUnit = 0 ; + if ( ! vdSplit0.empty()) + nUnit = int( vdSplit0.back()) ; for ( int z = int( vdSplit0.size() - 1) ; z >= 0 ; --z) { double dSplit = vdSplit0[z] ; int nSplit = int( dSplit) ; @@ -4340,13 +4335,19 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nUnit = nSplit ; pCrvU1->AddJoint( dSplit) ; switch( vnAddedOrNextIsRep0[z]) { - case 0 : vbRep1.insert( vbRep1.begin() + nSplit, false) ; break ; + case 0 : if( vbRep1[nSplit]) + ++ nRep1 ; + vbRep1.insert( vbRep1.begin() + nSplit, vbRep1[nSplit]) ; break ; // di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo case 1 : vbRep1.insert( vbRep1.begin() + nSplit, true) ; break ; - case 2 : vbRep1[nSplit] = true ; + case 2 : if ( vbRep1[nSplit]) + --nRep1 ; + else + vbRep1[nSplit] = true ; vbRep1.insert( vbRep1.begin() + nSplit, false) ; break ; } } - nUnit = int( vdSplit1.back()) ; + if( ! vdSplit1.empty()) + nUnit = int( vdSplit1.back()) ; for ( int z = int( vdSplit1.size() - 1) ; z >= 0 ; --z) { double dSplit = vdSplit1[z] ; int nSplit = int( dSplit) ; @@ -4358,16 +4359,47 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nUnit = nSplit ; pCrvU0->AddJoint( dSplit) ; switch( vnAddedOrNextIsRep1[z]) { - case 0 : vbRep0.insert( vbRep0.begin() + nSplit, false) ; break ; + case 0 : if( vbRep0[nSplit]) + ++ nRep0 ; + vbRep0.insert( vbRep0.begin() + nSplit, vbRep0[nSplit]) ; break ; // di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo case 1 : vbRep0.insert( vbRep0.begin() + nSplit, true) ; break ; - case 2 : vbRep0[nSplit] = true ; - vbRep0.insert( vbRep0.begin() + nSplit, false) ; break ; + case 2 : if( vbRep0[nSplit]) + -- nRep0 ; + else + vbRep0[nSplit] = true ; + vbRep0.insert( vbRep0.begin() + nSplit, false) ; break ; } } nSpanU0 = pCrvU0->GetCurveCount() ; nSpanU1 = pCrvU1->GetCurveCount() ; + //aggiusto i vettori delle ripetizioni in modo in modo che non arrivino mai ad essere contemporaneamente true + int nAddedSpan = 0 ; + int nCrv0 = 0 ; + int nCrv1 = 0 ; + while ( nAddedSpan < nSpanU0 + nAtStart0 + nAtEnd0 + nRep1) { + if ( nCrv0 >= nSpanU0) + nCrv0 = nSpanU0 - 1; + if ( nCrv1 >= nSpanU1) + nCrv1 = nSpanU1 - 1; + bool bRep0 = vbRep0[nCrv0] ; + bool bRep1 = vbRep1[nCrv1] ; + if ( bRep0 && bRep1 ) { + vbRep0[nCrv0] = false ; + bRep0 = false ; + vbRep1[nCrv1] = false ; + bRep1 = false ; + -- nRep0 ; + -- nRep1 ; + } + if ( ! bRep0) + ++ nCrv1 ; + if ( ! bRep1) + ++ nCrv0 ; + ++nAddedSpan ; + } + // trovo il numero di span che dovrà avere la superficie // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) nSpanU = nSpanU0 + nAtStart0 + nAtEnd0 + nRep1 ; @@ -4377,9 +4409,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; // aggiungo i punti di controllo scorrendo in contemporanea le due curve - int nAddedSpan = 0 ; - int nCrv0 = 0 ; - int nCrv1 = 0 ; + nAddedSpan = 0 ; + nCrv0 = 0 ; + nCrv1 = 0 ; bool bLast0 = false ; bool bLast1 = false ; while ( nAddedSpan < nSpanU) { @@ -4392,24 +4424,25 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bLast1 = true ; } bool bRep0 = vbRep0[nCrv0] ; + bool bRep1 = vbRep1[nCrv1] ; const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCrv0)) ; for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 - if ( vbRep1[nCrv1]) + if ( bRep1 || bLast0) nInd = ! bLast0 ? 0 : nDegU ; if ( ! bRat) SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd)) ; else SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd), pSubCrv0->GetControlWeight( nInd)) ; } - if ( ! vbRep1[nCrv1]) + if ( ! bRep1) ++ nCrv0 ; const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv1)) ; for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 - if ( bRep0) + if ( bRep0 || bLast1) nInd = ! bLast1 ? 0 : nDegU ; if ( ! bRat) SetControlPoint( nSecondRowInd + nAddedSpan * nDegU + i, pSubCrv1->GetControlPoint( nInd)) ; From c7035305e2d20af1ccc5f4b3a247c8a099d0d941 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 9 Jul 2024 15:47:47 +0200 Subject: [PATCH 38/45] =?UTF-8?q?EgtGeomKernel=20:=20-=20correzione=20alle?= =?UTF-8?q?=20rigate=20Bezier=20nella=20modalit=C3=A0=20MinDist.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d145113..fde7db5 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3884,7 +3884,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nSecondRowInd = nDegU * nSpanU + 1 ; // se sto usando la ISOPARM o la MINDIST semplice allora collego più span di una curva allo stesso punto - // ( aggiungo virtualmente delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) + // ( aggiungo delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) if ( nRuledType != RLT_B_MINDIST_PLUS){ if ( nRuledType == RLT_B_MINDIST) { // creo le liste di punti per le isoparametriche in U @@ -3929,7 +3929,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } ++ nCount0 ; // ripeto l'ultimo punto aggiunto alla riga 2 - //int nInd = nIndMatch == nSpanU1 ? nIndMatch - 1 : nIndMatch ; int nInd = nIndMatch - 1 ; const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { @@ -3945,10 +3944,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // qui devo capire se aggiungere la nuova sottocurva prima o dopo la ripetizione dei punti // se il match del punto della U1 è uguale al punto a cui ero arrivato sulla U0 allora prima aggiungo la ripetizione di punti // se invece il match è più avanti allora aggiuno prima la curva e poi la ripetzione di punti - bool bSubCurveAddedFirst = false ; - if ( vPnt1Match[vPnt0Match[i+1].second].second != i+1 ) { - bSubCurveAddedFirst = true ; - // aggiungo una sottocurva dalla prima curva + bool bSubCurveAddedFirst = true ; + for ( int z = vPnt0Match[i].second ; z <= vPnt0Match[i+1].second ; ++z) + bSubCurveAddedFirst = bSubCurveAddedFirst && vPnt1Match[z].second != i ; + + if( bSubCurveAddedFirst) { + // aggiungo una sottocurva dalla curva U0 pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { if ( ! bRat0) @@ -3959,11 +3960,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nCount0 ; } - // ripeto l'ultimo punto aggiunto per il numero di curve balzate della seconda curva - 1 + // ripeto l'ultimo punto aggiunto per il numero di curve balzate - 1 della curva U1 for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i != 0 ? i - 1 : i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - int nPoint = nCount0 == 0 && ! bSubCurveAddedFirst ? 0 : nDegU ; + int nPoint = i == 0 && ! bSubCurveAddedFirst ? 0 : nDegU ; if ( ! bRat0) SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; else @@ -3971,9 +3972,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } ++ nCount0 ; } - // se non l'ho già aggiunta prima aggiungo una sottocurva della prima curva + // se non l'ho già aggiunta prima aggiungo una sottocurva della U0 if( ! bSubCurveAddedFirst) { - // aggiungo una sottocurva dalla prima curva pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { if ( ! bRat0) @@ -3985,7 +3985,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } - // aggiungo tutte le sottocurve che ho balzato della seconda + // aggiungo tutte le sottocurve che ho balzato della curva U1 for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { @@ -3999,12 +3999,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } - //controllo se ho aggiunto tutti i punti della seconda curva + //controllo se ho aggiunto tutti i punti della curva U1 if ( vPnt0Match.back().second != nSpanU1) { - // riaggiungo l'ultimo punto + // riaggiungo l'ultimo punto della U0 const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSpanU0 - 1)) ; int nPoint = nDegU ; - while( nCount0 - 1 < nSpanU1) { + while( nCount0 < nSpanU) { for ( int j = 1 ; j < nLastPoint ; ++j) { if ( ! bRat0) SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; @@ -4014,7 +4014,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nCount0 ; } - // aggiungo le restanti sottocurve della curva 2 + // aggiungo le restanti sottocurve della curva U1 int nCrv1 = vPnt0Match.back().second ; while( nCrv1 < nSpanU1) { const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv1)) ; From d54caf4ae3ccf19bc47bd4a93133b883dd756670 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 10 Jul 2024 08:52:47 +0200 Subject: [PATCH 39/45] EgtGeomKernel : - pulizia codice. --- SurfBezier.cpp | 417 ++++++++++++++++++++++++------------------------- 1 file changed, 208 insertions(+), 209 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index fde7db5..7b6f963 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3885,41 +3885,70 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // se sto usando la ISOPARM o la MINDIST semplice allora collego più span di una curva allo stesso punto // ( aggiungo delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) - if ( nRuledType != RLT_B_MINDIST_PLUS){ - if ( nRuledType == RLT_B_MINDIST) { - // creo le liste di punti per le isoparametriche in U - PNTIVECTOR vPnt0Match, vPnt1Match ; - bool bCommonPoint = false ; - AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; + if ( nRuledType == RLT_B_MINDIST) { + // creo le liste di punti per le isoparametriche in U + PNTIVECTOR vPnt0Match, vPnt1Match ; + bool bCommonPoint = false ; + AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; - // devo contare il numero di ripetizioni dei match nel mezzo delle curve, perché aumentano il numero di span della superficie!! - int nRep0 = 0 ; - int nIndMatch = 0 ; - int nIndMatchNext = 0 ; - for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { - nIndMatch = vPnt0Match[i].second ; - nIndMatchNext = vPnt0Match[i+1].second ; - if ( nIndMatch != nIndMatchNext) - nRep0 += nIndMatchNext - nIndMatch - 1; - } - int nRep1 = int( vPnt1Match.size() - 1) - vPnt0Match.back().second ; - // reinizializzo la superficie con il nuovo numero di span in U - nSpanU = nSpanU0 + nRep0 + nRep1 ; - if ( nSpanU < max(nSpanU0, nSpanU1)) - nSpanU = max(nSpanU0, nSpanU1) ; - nSecondRowInd = nDegU * nSpanU + 1 ; - Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // devo contare il numero di ripetizioni dei match nel mezzo delle curve, perché aumentano il numero di span della superficie!! + int nRep0 = 0 ; + int nIndMatch = 0 ; + int nIndMatchNext = 0 ; + for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { + nIndMatch = vPnt0Match[i].second ; + nIndMatchNext = vPnt0Match[i+1].second ; + if ( nIndMatch != nIndMatchNext) + nRep0 += nIndMatchNext - nIndMatch - 1; + } + int nRep1 = int( vPnt1Match.size() - 1) - vPnt0Match.back().second ; + // reinizializzo la superficie con il nuovo numero di span in U + nSpanU = nSpanU0 + nRep0 + nRep1 ; + if ( nSpanU < max(nSpanU0, nSpanU1)) + nSpanU = max(nSpanU0, nSpanU1) ; + nSecondRowInd = nDegU * nSpanU + 1 ; + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; - // numero di span aggiunte su U0 e U1 - nCount0 = 0 ; - nCount1 = 0 ; + // numero di span aggiunte su U0 e U1 + nCount0 = 0 ; + nCount1 = 0 ; - // scorro gli estremi delle sottocurve della curva 1 - for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { - nIndMatch = vPnt0Match[i].second ; - nIndMatchNext = vPnt0Match[i+1].second ; - const ICurveBezier* pSubCrv0 ; - if ( nIndMatch == nIndMatchNext) { + // scorro gli estremi delle sottocurve della curva 1 + for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { + nIndMatch = vPnt0Match[i].second ; + nIndMatchNext = vPnt0Match[i+1].second ; + const ICurveBezier* pSubCrv0 ; + if ( nIndMatch == nIndMatchNext) { + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + } + ++ nCount0 ; + // ripeto l'ultimo punto aggiunto alla riga 2 + int nInd = nIndMatch - 1 ; + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; + for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + int nPoint = nCount1 == 0 ? 0 : nDegU ; + if ( ! bRat0) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; + } + ++nCount1 ; + } + else { + // qui devo capire se aggiungere la nuova sottocurva prima o dopo la ripetizione dei punti + // se il match del punto della U1 è uguale al punto a cui ero arrivato sulla U0 allora prima aggiungo la ripetizione di punti + // se invece il match è più avanti allora aggiuno prima la curva e poi la ripetzione di punti + bool bSubCurveAddedFirst = true ; + for ( int z = vPnt0Match[i].second ; z <= vPnt0Match[i+1].second ; ++z) + bSubCurveAddedFirst = bSubCurveAddedFirst && vPnt1Match[z].second != i ; + + if( bSubCurveAddedFirst) { + // aggiungo una sottocurva dalla curva U0 pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { if ( ! bRat0) @@ -3928,84 +3957,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; } ++ nCount0 ; - // ripeto l'ultimo punto aggiunto alla riga 2 - int nInd = nIndMatch - 1 ; - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; - for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - int nPoint = nCount1 == 0 ? 0 : nDegU ; - if ( ! bRat0) - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; - else - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; - } - ++nCount1 ; } - else { - // qui devo capire se aggiungere la nuova sottocurva prima o dopo la ripetizione dei punti - // se il match del punto della U1 è uguale al punto a cui ero arrivato sulla U0 allora prima aggiungo la ripetizione di punti - // se invece il match è più avanti allora aggiuno prima la curva e poi la ripetzione di punti - bool bSubCurveAddedFirst = true ; - for ( int z = vPnt0Match[i].second ; z <= vPnt0Match[i+1].second ; ++z) - bSubCurveAddedFirst = bSubCurveAddedFirst && vPnt1Match[z].second != i ; - if( bSubCurveAddedFirst) { - // aggiungo una sottocurva dalla curva U0 - pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; - for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; - } - ++ nCount0 ; - } - - // ripeto l'ultimo punto aggiunto per il numero di curve balzate - 1 della curva U1 - for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { - pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i != 0 ? i - 1 : i)) ; - for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - int nPoint = i == 0 && ! bSubCurveAddedFirst ? 0 : nDegU ; - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; - } - ++ nCount0 ; - } - // se non l'ho già aggiunta prima aggiungo una sottocurva della U0 - if( ! bSubCurveAddedFirst) { - pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; - for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { - if ( ! bRat0) - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; - else - SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; - } - ++ nCount0 ; - } - - - // aggiungo tutte le sottocurve che ho balzato della curva U1 - for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { - pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; - for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { - if ( ! bRat) - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; - else - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; - } - ++ nCount1 ; - } - } - } - - //controllo se ho aggiunto tutti i punti della curva U1 - if ( vPnt0Match.back().second != nSpanU1) { - // riaggiungo l'ultimo punto della U0 - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSpanU0 - 1)) ; - int nPoint = nDegU ; - while( nCount0 < nSpanU) { - for ( int j = 1 ; j < nLastPoint ; ++j) { + // ripeto l'ultimo punto aggiunto per il numero di curve balzate - 1 della curva U1 + for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i != 0 ? i - 1 : i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + int nPoint = i == 0 && ! bSubCurveAddedFirst ? 0 : nDegU ; if ( ! bRat0) SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; else @@ -4013,113 +3971,95 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } ++ nCount0 ; } - - // aggiungo le restanti sottocurve della curva U1 - int nCrv1 = vPnt0Match.back().second ; - while( nCrv1 < nSpanU1) { - const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv1)) ; - for ( int j = 1 ; j < nLastPoint ; ++j) { - if ( ! bRat1) - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; + // se non l'ho già aggiunta prima aggiungo una sottocurva della U0 + if( ! bSubCurveAddedFirst) { + pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( i)) ; + for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; else - SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; + } + ++ nCount0 ; + } + + + // aggiungo tutte le sottocurve che ho balzato della curva U1 + for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { + pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nIndMatch + k)) ; + for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( j)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; } ++ nCount1 ; - ++ nCrv1 ; } } } - if ( nRuledType == RLT_B_ISOPAR) { - // inizializzo la superficie - Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; - Point3d ptP0Start ; pCrvU0->GetStartPoint( ptP0Start) ; - Point3d ptP1Start ; pCrvU1->GetStartPoint( ptP1Start) ; - // setto i primi due punti delle righe - nCount0 = 0 ; // sottocurva su pCrvU0 - if ( ! bRat) - SetControlPoint( 0, ptP0Start) ; - else - SetControlPoint( 0, ptP0Start, vdW0[0]) ; - nCount1 = 0 ; // sottocurva su pCrvU1 - if ( ! bRat) - SetControlPoint( nSecondRowInd, ptP1Start) ; - else - SetControlPoint( nSecondRowInd, ptP1Start, vdW1[0]) ; - - INTVECTOR vMatch ; - int nLong = 0 ; - // prendo la polyline con più punti e scelgo a quali punti dell'altra polyline vanno associati - FindMatchByParam( plU0, plU1, vMatch,nLong) ; - - for( int i = 0 ; i < int( vMatch.size() - 1) ; ++i) { - int nCount = i ; // span in U aggiunte - // scorro i punti della polyline più lunga - // se il punto corrente e il successivo sono associati allo stesso punto dell'altra polyline - // allora devo aggiungere la sottocurva della curva più lunga e ripetere l'ultimo punto aggiunto dell'altra polyline - // se il corrente e il successivo sono associati a punti successivi - // allora devo aggiungere una sottocurva per ognuna delle due curve - if ( vMatch[i] == vMatch[i+1]) { - // se la curva più lunga è la prima - if ( nLong == 0) { - // aggiungo la curva sulla prima riga - for ( int i = 1 ; i < nLastPoint ; ++i) { - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCount0)) ; - Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; - if ( ! bRat) - SetControlPoint( nCount * nDegU + i, ptCtrl) ; - else { - double dW = pSubCrv0->GetControlWeight( i) ; - SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; - } - } - ++ nCount0 ; - // riaggungo lo start point sulla seconda riga - // o end point se ho già aggiunto tutte le curve - int nInd = nCount1 < nSpanU1 ? 0 : nDegU ; - int nSubCrv = nCount1 < nSpanU1 ? nCount1 : nSpanU1 - 1 ; - const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nSubCrv)) ; - Point3d ptCtrl = pSubCrv1->GetControlPoint( nInd) ; - for ( int i = 1 ; i < nLastPoint ; ++i) { - if ( ! bRat) - SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; - else { - double dW = pSubCrv1->GetControlWeight( i) ; - SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; - } - } - } - else { - // aggiungo la curva sulla seconda riga - for ( int i = 1 ; i < nLastPoint ; ++i) { - const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCount1)) ; - Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; - if ( ! bRat) - SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; - else { - double dW = pSubCrv1->GetControlWeight( i) ; - SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; - } - } - ++ nCount1 ; - // riaggungo lo start point sulla prima riga - // o end point se ho già aggiunto tutte le curve - int nInd = nCount0 < nSpanU0 ? 0 : nDegU ; - int nSubCrv = nCount0 < nSpanU0 ? nCount0 : nSpanU0 - 1 ; - const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSubCrv)) ; - Point3d ptCtrl = pSubCrv0->GetControlPoint( nInd) ; - for ( int i = 1 ; i < nLastPoint ; ++i) { - if ( ! bRat) - SetControlPoint( nCount * nDegU + i, ptCtrl) ; - else { - double dW = pSubCrv0->GetControlWeight( i) ; - SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; - } - } - } + //controllo se ho aggiunto tutti i punti della curva U1 + if ( vPnt0Match.back().second != nSpanU1) { + // riaggiungo l'ultimo punto della U0 + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSpanU0 - 1)) ; + int nPoint = nDegU ; + while( nCount0 < nSpanU) { + for ( int j = 1 ; j < nLastPoint ; ++j) { + if ( ! bRat0) + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; + else + SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; } - // altrimenti aggiungo una sottocurva da entrambe le curve - else { + ++ nCount0 ; + } + + // aggiungo le restanti sottocurve della curva U1 + int nCrv1 = vPnt0Match.back().second ; + while( nCrv1 < nSpanU1) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCrv1)) ; + for ( int j = 1 ; j < nLastPoint ; ++j) { + if ( ! bRat1) + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j)) ; + else + SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv1->GetControlPoint( j), pSubCrv1->GetControlWeight( j)) ; + } + ++ nCount1 ; + ++ nCrv1 ; + } + } + } + else if ( nRuledType == RLT_B_ISOPAR) { + // inizializzo la superficie + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; + Point3d ptP0Start ; pCrvU0->GetStartPoint( ptP0Start) ; + Point3d ptP1Start ; pCrvU1->GetStartPoint( ptP1Start) ; + // setto i primi due punti delle righe + nCount0 = 0 ; // sottocurva su pCrvU0 + if ( ! bRat) + SetControlPoint( 0, ptP0Start) ; + else + SetControlPoint( 0, ptP0Start, vdW0[0]) ; + nCount1 = 0 ; // sottocurva su pCrvU1 + if ( ! bRat) + SetControlPoint( nSecondRowInd, ptP1Start) ; + else + SetControlPoint( nSecondRowInd, ptP1Start, vdW1[0]) ; + + INTVECTOR vMatch ; + int nLong = 0 ; + // prendo la polyline con più punti e scelgo a quali punti dell'altra polyline vanno associati + FindMatchByParam( plU0, plU1, vMatch,nLong) ; + + for( int i = 0 ; i < int( vMatch.size() - 1) ; ++i) { + int nCount = i ; // span in U aggiunte + // scorro i punti della polyline più lunga + // se il punto corrente e il successivo sono associati allo stesso punto dell'altra polyline + // allora devo aggiungere la sottocurva della curva più lunga e ripetere l'ultimo punto aggiunto dell'altra polyline + // se il corrente e il successivo sono associati a punti successivi + // allora devo aggiungere una sottocurva per ognuna delle due curve + if ( vMatch[i] == vMatch[i+1]) { + // se la curva più lunga è la prima + if ( nLong == 0) { // aggiungo la curva sulla prima riga for ( int i = 1 ; i < nLastPoint ; ++i) { const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCount0)) ; @@ -4132,6 +4072,22 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } ++ nCount0 ; + // riaggungo lo start point sulla seconda riga + // o end point se ho già aggiunto tutte le curve + int nInd = nCount1 < nSpanU1 ? 0 : nDegU ; + int nSubCrv = nCount1 < nSpanU1 ? nCount1 : nSpanU1 - 1 ; + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nSubCrv)) ; + Point3d ptCtrl = pSubCrv1->GetControlPoint( nInd) ; + for ( int i = 1 ; i < nLastPoint ; ++i) { + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv1->GetControlWeight( i) ; + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; + } + } + } + else { // aggiungo la curva sulla seconda riga for ( int i = 1 ; i < nLastPoint ; ++i) { const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCount1)) ; @@ -4144,10 +4100,50 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } ++ nCount1 ; + // riaggungo lo start point sulla prima riga + // o end point se ho già aggiunto tutte le curve + int nInd = nCount0 < nSpanU0 ? 0 : nDegU ; + int nSubCrv = nCount0 < nSpanU0 ? nCount0 : nSpanU0 - 1 ; + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nSubCrv)) ; + Point3d ptCtrl = pSubCrv0->GetControlPoint( nInd) ; + for ( int i = 1 ; i < nLastPoint ; ++i) { + if ( ! bRat) + SetControlPoint( nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv0->GetControlWeight( i) ; + SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; + } + } } } + // altrimenti aggiungo una sottocurva da entrambe le curve + else { + // aggiungo la curva sulla prima riga + for ( int i = 1 ; i < nLastPoint ; ++i) { + const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU0->GetCurve( nCount0)) ; + Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; + if ( ! bRat) + SetControlPoint( nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv0->GetControlWeight( i) ; + SetControlPoint( nCount * nDegU + i, ptCtrl, dW) ; + } + } + ++ nCount0 ; + // aggiungo la curva sulla seconda riga + for ( int i = 1 ; i < nLastPoint ; ++i) { + const ICurveBezier* pSubCrv1 = GetCurveBezier( pCrvU1->GetCurve( nCount1)) ; + Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; + if ( ! bRat) + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl) ; + else { + double dW = pSubCrv1->GetControlWeight( i) ; + SetControlPoint( nSecondRowInd + nCount * nDegU + i, ptCtrl, dW) ; + } + } + ++ nCount1 ; + } } - } // spezzo le curve di bezier dove è necessario aggiungere dei punti else if ( nRuledType == RLT_B_MINDIST_PLUS ) { // probabilmente se questo funziona bene non serve la modilità ISOPARM_SMOOTH @@ -4371,7 +4367,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } - nSpanU0 = pCrvU0->GetCurveCount() ; nSpanU1 = pCrvU1->GetCurveCount() ; //aggiusto i vettori delle ripetizioni in modo in modo che non arrivino mai ad essere contemporaneamente true @@ -4454,6 +4449,10 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nAddedSpan ; } } + else if ( RLT_B_LENPAR ) { + // da implementare + return false ; + } return true ; } From 79b470b18b2e108527331b7b3897772de96e64be Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 10 Jul 2024 16:41:07 +0200 Subject: [PATCH 40/45] EgtGeomKernel : - correzione alle rigate con Bezier. --- SurfBezier.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 7b6f963..ff0588b 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -4394,6 +4394,15 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nCrv0 ; ++nAddedSpan ; } + // se non sono arrivato all'ultima curva su U0 o U1 vuol dire che ho creato delle ripetizioni che non ho contato prima + if( nCrv1 < nSpanU1) + nRep1 += nSpanU1 - nCrv1 ; + for ( int z = int( vbRep1.size() - 1) ; z >= nCrv1 ; --z) + vbRep1[z] = true ; + if( nCrv0 < nSpanU0) + nRep0 += nSpanU0 - nCrv0 ; + for ( int z = int( vbRep0.size() - 1) ; z >= nCrv0 ; --z) + vbRep0[z] = true ; // trovo il numero di span che dovrà avere la superficie // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) From f7a28447fb702387262e0bb2f98b68dce26e88fa Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 10 Jul 2024 16:41:34 +0200 Subject: [PATCH 41/45] EgtGeomKernel : - correzione alla triangolazione delle bezier. --- Tree.cpp | 259 ++++++++++++++++++++++++++++--------------------------- Tree.h | 2 +- 2 files changed, 133 insertions(+), 128 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 69ab52a..aac78f5 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1610,11 +1610,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM // trimmata else { POLYLINEVECTOR vPolygonsBasic ; - POLYLINEVECTOR vPolygonsBasic3d ; - if ( bForTriangulation) - GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ; - else - GetPolygonsBasic( vPolygonsBasic) ; + GetPolygonsBasic( vPolygonsBasic) ; // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim m_vCEdge2D.clear() ; for ( int i = 0 ; i < 4 ; ++i) { @@ -1624,6 +1620,11 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM // percorro i loop, trovo le intersezioni con le celle e le categorizzo if ( ! TraceLoopLabelCell( vPolygonsBasic)) return false ; + POLYLINEVECTOR vPolygonsBasic3d ; + if ( bForTriangulation) { + vPolygonsBasic.clear() ; + GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ; + } // scorro sulle celle e costruisco i poligoni int nCells = int( vPolygonsBasic.size()) ; for ( int i = 0 ; i < nCells ; ++ i) { @@ -1660,12 +1661,15 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM // in questo for analizzo solo i loop che tagliano la cella while( (int)vToCheck.size() != 0) { int nPolyBefore = nPoly ; - CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i], vPolygonsBasic3d[i]) ; + PolyLine pl3d ; + if( bForTriangulation) + pl3d = vPolygonsBasic3d[i] ; + CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i], pl3d) ; if ( nPolyBefore == nPoly) break ; } // ora analizzo anche i loop che sono contenuti nella cella - CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk) ; + CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, bForTriangulation) ; } } return true ; @@ -1747,7 +1751,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; vVertices.push_back( pt) ; - vVertices3d.push_back( m_mVert[j][1]) ; + vVertices3d.push_back( m_mVert[j][2]) ; } } else { @@ -1772,7 +1776,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; vVertices.push_back( pt) ; - vVertices3d.push_back( m_mVert[j][1]) ; + vVertices3d.push_back( m_mVert[j][0]) ; } } else { @@ -1805,7 +1809,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; vVertices.push_back( pt) ; - vVertices3d.push_back( m_mVert[j][3]) ; + vVertices3d.push_back( m_mVert[j][0]) ; } } else { @@ -1831,7 +1835,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; vVertices.push_back( pt) ; - vVertices3d.push_back( m_mVert[j][3]) ; + vVertices3d.push_back( m_mVert[j][2]) ; } } else { @@ -2951,14 +2955,19 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX vEdgeVertex[1].push_back( m_mTree[nId].GetTopLeft()) ; vEdgeVertex[2].push_back( m_mTree[nId].GetBottomLeft()) ; vEdgeVertex[3].push_back( m_mTree[nId].GetBottomRight()) ; - vEdgeVertex3d[0].push_back( m_mVert[nId][2]) ; - vEdgeVertex3d[1].push_back( m_mVert[nId][3]) ; - vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ; - vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ; + // capisco se sono in modalità ForTriangulation + bool bForTriangulation = plCell3d.GetPointNbr() != 0 ; + if ( bForTriangulation) { + vEdgeVertex3d[0].push_back( m_mVert[nId][2]) ; + vEdgeVertex3d[1].push_back( m_mVert[nId][3]) ; + vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ; + vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ; + } // la PolyLine è riempita a partire dal lato bottom Point3d ptStart, pt3d ; plCell.GetFirstPoint( ptStart) ; - plCell3d.GetFirstPoint( pt3d) ; + if ( bForTriangulation) + plCell3d.GetFirstPoint( pt3d) ; INTVECTOR vEdge = { 2, 3, 0, 1} ; for ( int p = 0 ; p < 4 ; ++ p) { int j = vEdge[p] ; @@ -2966,9 +2975,12 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX if ( j == 3) next = 0 ; Point3d ptToAdd ; - while ( plCell.GetNextPoint( ptToAdd) && plCell3d.GetNextPoint( pt3d) && ! AreSamePointExact( ptToAdd, vEdgeVertex[next][0])) { + while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, vEdgeVertex[next][0])) { vEdgeVertex[j].push_back( ptToAdd) ; - vEdgeVertex3d[j].push_back( pt3d) ; + if ( bForTriangulation) { + plCell3d.GetNextPoint( pt3d) ; + vEdgeVertex3d[j].push_back( pt3d) ; + } } } @@ -3015,46 +3027,8 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX Vector3d vLast = ptLast - ptSecondToLast ; vLast.Normalize() ; Vector3d vEdge ; - //if ( AreSameEdge( nEdge, 0)) { - // if ( AreSamePointExact( ptLast, ptTl)) { - // vEdge = m_mTree[nId].GetBottomLeft() - ptTl ; - // vEdge.Normalize() ; - // if ( AreOppositeVectorApprox( vLast, vEdge)) { - // plTrimmedPoly.EraseLastUPoint() ; - // nEdge = 1 ; - // } - // } - //} - //else if ( AreSameEdge( nEdge, 1) && AreSamePointExact( ptLast, m_mTree[nId].GetBottomLeft())) { - // vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; - // vEdge.Normalize() ; - // if ( AreOppositeVectorApprox( vLast, vEdge)) { - // plTrimmedPoly.EraseLastUPoint() ; - // nEdge = 2 ; - // } - //} - //else if ( AreSameEdge( nEdge, 2)) { - // if ( AreSamePointExact( ptLast, ptBr)) { - // vEdge = m_mTree[nId].GetTopRight() - ptBr ; - // vEdge.Normalize() ; - // if ( AreOppositeVectorApprox( vLast, vEdge)) { - // plTrimmedPoly.EraseLastUPoint() ; - // nEdge = 3 ; - // } - // } - //} - //else if ( AreSameEdge( nEdge, 3) && AreSamePointExact( ptLast, m_mTree[nId].GetTopRight())) { - // vEdge = ptTl - m_mTree[nId].GetTopRight() ; - // vEdge.Normalize() ; - // if ( AreOppositeVectorApprox( vLast, vEdge)) { - // plTrimmedPoly.EraseLastUPoint() ; - // nEdge = 0 ; - // } - //} - // estendo: se l'ultimo tratto è sovrapposto e controverso allora elimino l'ultimo punto if ( nEdge == 0 || nEdge == 7 ) { - //vEdge = ptTl - m_mTree[nId].GetTopRight() ; vEdge.Set( 1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3063,7 +3037,6 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX } } else if ( nEdge == 1 || nEdge == 4 ) { - //vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; vEdge.Set( 0,-1,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3072,7 +3045,6 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX } } else if ( nEdge == 2 || nEdge == 5 ) { - //vEdge = ptTl - m_mTree[nId].GetTopRight() ; vEdge.Set( -1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3081,7 +3053,6 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX } } else if ( nEdge == 3 || nEdge == 6 ) { - //vEdge = m_mTree[nId].GetTopRight() - ptBr ; vEdge.Set( 0,1,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3218,12 +3189,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX if ( dArea > 0) { vCellPolygons.push_back( plTrimmedPoly) ; vPolygons.push_back( vCellPolygons) ; - vCellPolygons3d.push_back( plTrimmedPoly3d) ; - vPolygons3d.push_back( vCellPolygons3d) ; + vCellPolygons.clear() ; + if( bForTriangulation) { + vCellPolygons3d.push_back( plTrimmedPoly3d) ; + vPolygons3d.push_back( vCellPolygons3d) ; + vCellPolygons3d.clear() ; + } ++ nPoly ; vnParentChunk.push_back( inA.nChunk) ; - vCellPolygons.clear() ; - vCellPolygons3d.clear() ; } c = 0 ; @@ -3247,15 +3220,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX //---------------------------------------------------------------------------- bool -Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk) +Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation) { // vettore dei poligoni ( loop) della cella nId POLYLINEVECTOR vCellPolygons ; POLYLINEVECTOR vCellPolygons3d ; // costruisco i poligoni partendo dal vettore delle intersezioni int nId = m_vnLeaves[nLeafId] ; - //PolyLine plTrimmedPoly ; - //PolyLine plTrimmedPoly3d ; + //capisco se sono in modalità ForTriangulation // loop interni in una cella intersecata int nChunkBiggestCW = -1 ; @@ -3308,14 +3280,16 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR vCellPolygons.push_back( plInLoop) ; vPolygons.push_back( vCellPolygons) ; ++ nPoly ; - plInLoop3d.AddUPoint( 0, m_mVert[nId][2]); - plInLoop3d.AddUPoint( 1, m_mVert[nId][3]); - plInLoop3d.AddUPoint( 2, m_mVert[nId][0]); - plInLoop3d.AddUPoint( 3, m_mVert[nId][1]); - vCellPolygons3d.push_back( plInLoop3d) ; - vPolygons3d.push_back( vCellPolygons3d) ; - vCellPolygons3d.clear() ; - plInLoop3d.Clear() ; + if ( bForTriangulation) { + plInLoop3d.AddUPoint( 0, m_mVert[nId][2]); + plInLoop3d.AddUPoint( 1, m_mVert[nId][3]); + plInLoop3d.AddUPoint( 2, m_mVert[nId][0]); + plInLoop3d.AddUPoint( 3, m_mVert[nId][1]); + vCellPolygons3d.push_back( plInLoop3d) ; + vPolygons3d.push_back( vCellPolygons3d) ; + vCellPolygons3d.clear() ; + plInLoop3d.Clear() ; + } // imposto il chunk del loop CW più grande ( il primo che ho incontrato) vnParentChunk.push_back( nChunkBiggestCW) ; vCellPolygons.clear() ; @@ -3328,12 +3302,15 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR int k = 0 ; for ( Point3d ptInt : inA.vpt) { plInLoop.AddUPoint( k, ptInt) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptInt.x / SBZ_TREG_COEFF, ptInt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - plInLoop3d.AddUPoint( k, pt3d) ; + if ( bForTriangulation) { + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptInt.x / SBZ_TREG_COEFF, ptInt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plInLoop3d.AddUPoint( k, pt3d) ; + } ++ k ; } plInLoop.Close() ; - plInLoop3d.Close() ; + if ( bForTriangulation) + plInLoop3d.Close() ; bool bAdded = false ; // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto if ( ! inA.bCCW) { @@ -3343,9 +3320,11 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR for ( int r = 0 ; r < nPoly ; ++r) { if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk) { vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ; - vPolygons3d[nOtherPoly - r - 1].push_back( plInLoop3d) ; plInLoop.Clear() ; - plInLoop3d.Clear() ; + if ( bForTriangulation) { + vPolygons3d[nOtherPoly - r - 1].push_back( plInLoop3d) ; + plInLoop3d.Clear() ; + } bAdded = true ; break ; } @@ -3354,17 +3333,20 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR if ( ! bAdded) { vCellPolygons.push_back( plInLoop) ; vPolygons.push_back( vCellPolygons) ; - vCellPolygons3d.push_back( plInLoop3d) ; - vPolygons3d.push_back( vCellPolygons3d) ; - ++ nPoly ; - vnParentChunk.push_back( inA.nChunk) ; plInLoop.Clear() ; vCellPolygons.clear() ; - plInLoop3d.Clear() ; - vCellPolygons3d.clear() ; + if ( bForTriangulation) { + vCellPolygons3d.push_back( plInLoop3d) ; + vPolygons3d.push_back( vCellPolygons3d) ; + plInLoop3d.Clear() ; + vCellPolygons3d.clear() ; + } + ++ nPoly ; + vnParentChunk.push_back( inA.nChunk) ; } plInLoop.Clear() ; - plInLoop3d.Clear() ; + if ( bForTriangulation) + plInLoop3d.Clear() ; } else continue ; @@ -3525,12 +3507,17 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const bool Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d) const { + //capisco se sono in modalità ForTriangulation + bool bForTriangulation = plTrimmedPoly3d.GetPointNbr() ; + // se è il primo punto della PolyLine lo aggiungo if ( plTrimmedPoly.GetPointNbr() == 0) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if ( bForTriangulation) { + Point3d pt3d ; + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; return true ; } @@ -3570,12 +3557,14 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe else ptVert = ptToAdd ; plTrimmedPoly.AddUPoint( c, ptVert) ; - Point3d pt3d ; - if ( nVert != -1) - pt3d = m_mVert.at(nId)[nVert] ; - else - m_pSrfBz->GetPointD1D2( ptVert.x, ptVert.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation){ + Point3d pt3d ; + if ( nVert != -1) + pt3d = m_mVert.at(nId)[nVert] ; + else + m_pSrfBz->GetPointD1D2( ptVert.x, ptVert.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; return true ; } @@ -3587,17 +3576,20 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[0][t] ; if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[0][t]) ; + if( bForTriangulation) + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[0][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[1][0])) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[1][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation){ + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[1][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[1][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; } // edge 1 @@ -3606,17 +3598,20 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[1][t] ; if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[1][t]) ; + if( bForTriangulation) + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[1][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[2][0])) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[2][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation) { + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[2][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[2][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; } // edge 2 @@ -3625,17 +3620,20 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[2][t] ; if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[2][t]) ; + if( bForTriangulation) + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[2][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[3][0])) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[3][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation){ + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[3][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[3][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; } // edge 3 @@ -3644,33 +3642,40 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[3][t] ; if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[3][t]) ; + if( bForTriangulation) + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[3][t]) ; ++ c ; } } plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[0][0])) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[0][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation) { + Point3d pt3d ; + if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[0][0])) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[0][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; } // sono allineato con un lato, ma NON sono su un lato // aggiungo e basta else { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation) { + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; } } // non su un edge, quindi aggiungo e basta else { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if( bForTriangulation) { + Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } ++ c ; } return true ; diff --git a/Tree.h b/Tree.h index 7559dbf..108efd4 100644 --- a/Tree.h +++ b/Tree.h @@ -277,7 +277,7 @@ class Tree bool FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim // resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni. - bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella + bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR. bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3) From 695350d3f6ea26ef3eaa424a37896ae81f566251 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 12 Jul 2024 12:04:41 +0200 Subject: [PATCH 42/45] =?UTF-8?q?EgtGeomKernel=20:=20-=20correzione=20per?= =?UTF-8?q?=20evitare=20errori=20di=20triangolazione=20in=20prossimit?= =?UTF-8?q?=C3=A0=20dei=20poli=20in=20sup=20di=20Bezier.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tree.cpp | 348 +++++++++++++++++++++++++++++++++---------------------- Tree.h | 9 +- 2 files changed, 216 insertions(+), 141 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index aac78f5..0b26e2a 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1611,6 +1611,10 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM else { POLYLINEVECTOR vPolygonsBasic ; GetPolygonsBasic( vPolygonsBasic) ; + POLYLINEVECTOR vPolygons ; + POLYLINEVECTOR vPolygonsBasic3d ; + if ( bForTriangulation) + GetPolygonsBasic( vPolygons, vPolygonsBasic3d) ; // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim m_vCEdge2D.clear() ; for ( int i = 0 ; i < 4 ; ++i) { @@ -1620,11 +1624,6 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM // percorro i loop, trovo le intersezioni con le celle e le categorizzo if ( ! TraceLoopLabelCell( vPolygonsBasic)) return false ; - POLYLINEVECTOR vPolygonsBasic3d ; - if ( bForTriangulation) { - vPolygonsBasic.clear() ; - GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ; - } // scorro sulle celle e costruisco i poligoni int nCells = int( vPolygonsBasic.size()) ; for ( int i = 0 ; i < nCells ; ++ i) { @@ -1858,6 +1857,9 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL vVertices3d.push_back( m_mVert[nId][0]) ; vnVert.push_back( int(vVertices.size()) - 1) ; + BOOLVECTOR vbKeepPoint( vVertices.size()) ; + fill( vbKeepPoint.begin(), vbKeepPoint.end(), true) ; + if ( bForTriangulation){ // ora devo controllare se uno dei lati della cella è collassato in un punto. // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra @@ -1867,15 +1869,20 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] ) {// lati contati a partire da quello sopra in senso CCW - vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + //vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + //vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + vbKeepPoint[vnVert[1]] = false ; + m_mTree[nId].m_nVertToErase = 1 ; // ptBr } else if ( vbBonusVert[3] ) { - // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVertices.pop_back() ; - vVertices[0] = vVertices.end()[-1] ; - vVertices3d.pop_back() ; - vVertices3d[0] = vVertices3d.end()[-1] ; + //// dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + //vVertices.pop_back() ; + //vVertices[0] = vVertices.end()[-1] ; + //vVertices3d.pop_back() ; + //vVertices3d[0] = vVertices3d.end()[-1] ; + vbKeepPoint[0] = false ; + vbKeepPoint.back() = false ; + m_mTree[nId].m_nVertToErase = 0 ; // ptBL } } } @@ -1884,12 +1891,16 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] ){ // lati contati a partire da quello sopra in senso CCW - vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + //vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + //vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + vbKeepPoint[vnVert[1]] = false ; + m_mTree[nId].m_nVertToErase = 1 ; // ptBr } else if ( vbBonusVert[2] ){ - vVertices.erase(vVertices.begin() + vnVert[2]) ; - vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + //vVertices.erase(vVertices.begin() + vnVert[2]) ; + //vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + vbKeepPoint[vnVert[2]] = false ; + m_mTree[nId].m_nVertToErase = 2 ; // ptTR } } } @@ -1898,12 +1909,16 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] ){ // lati contati a partire da quello sopra in senso CCW - vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW - vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + //vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW + //vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + vbKeepPoint[vnVert[2]] = false ; + m_mTree[nId].m_nVertToErase = 2 ; // ptTR } else if ( vbBonusVert[3] ) { - vVertices.erase(vVertices.begin() + vnVert[3]) ; - vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + //vVertices.erase(vVertices.begin() + vnVert[3]) ; + //vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl } } } @@ -1912,15 +1927,20 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] ) { // lati contati a partire da quello sopra in senso CCW - // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVertices.pop_back() ; - vVertices[0] = vVertices.end()[-1] ; - vVertices3d.pop_back() ; - vVertices3d[0] = vVertices3d.end()[-1] ; + //// dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + //vVertices.pop_back() ; + //vVertices[0] = vVertices.end()[-1] ; + //vVertices3d.pop_back() ; + //vVertices3d[0] = vVertices3d.end()[-1] ; + vbKeepPoint[0] = false ; + vbKeepPoint.back() = false ; + m_mTree[nId].m_nVertToErase = 0 ; // ptBL } else if ( vbBonusVert[2] ) { - vVertices.erase(vVertices.begin() + vnVert[3]) ; - vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + //vVertices.erase(vVertices.begin() + vnVert[3]) ; + //vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl } } } @@ -1947,6 +1967,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL vVertices.back() = vVertices.at( 0) ; rotate( vVertices3d.begin(), vVertices3d.begin() + 1,vVertices3d.end()) ; vVertices3d.back() = vVertices3d.at( 0) ; + rotate( vbKeepPoint.begin(), vbKeepPoint.begin() + 1,vbKeepPoint.end()) ; + vbKeepPoint.back() = vbKeepPoint.at( 0) ; } } } @@ -1956,8 +1978,11 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL m_vPolygons3d.emplace_back() ; m_vPolygons3d.back().emplace_back() ; for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { - m_vPolygons.back().back().AddUPoint( i, vVertices.at( i)) ; - m_vPolygons3d.back().back().AddUPoint( i, vVertices3d.at( i)) ; + int dPar = i ; + if( ! vbKeepPoint[i]) + dPar = -1 ; + m_vPolygons.back().back().AddUPoint( dPar, vVertices.at( i)) ; + m_vPolygons3d.back().back().AddUPoint( dPar, vVertices3d.at( i)) ; } } @@ -2281,7 +2306,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // trovo l'intersezione e passo alla cella successiva. nId viene aggiornato dalla funzione FindInters // se non trovo l'intersezione vuol dire che non sono nella cella giusta! // al precedente FindInters avrei dovuto passare di cella - if ( ! FindInters( nId, clTrim, vptInters, true)) { + if ( ! FindInters( nId, clTrim, vplPolygons[nIdPolygon], vptInters, true)) { // scarterò il punto molto vicino al lato e tengo solo l'intersezione del trim col lato if( vptInters.size() != 0) vptInters.pop_back() ; @@ -2291,7 +2316,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) clTrim.Set( ptTStart, ptTEnd) ; clTrim.ExtendEndByLen( EPS_SMALL * 2) ; clTrim.ExtendStartByLen( EPS_SMALL * 2) ; - if ( ! FindInters( nId, clTrim, vptInters, true)) + if ( ! FindInters( nId, clTrim, vplPolygons[nIdPolygon], vptInters, true)) return false ; bEraseNextPoint = true ; } @@ -2517,97 +2542,122 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) //---------------------------------------------------------------------------- bool -Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters) +Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters) { - CurveLine clEdge , clEdge2 ; - Point3d ptStart , ptEnd ; - clTrim.GetStartPoint( ptStart) ; - clTrim.GetEndPoint( ptEnd) ; - // trovo da quale lato sto uscendo Point3d ptTR = m_mTree[nId].GetTopRight() ; Point3d ptBL = m_mTree[nId].GetBottomLeft() ; Point3d ptTl( ptBL.x , ptTR.y) ; Point3d ptBr( ptTR.x , ptBL.y) ; int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario - // oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario - // -1 se la curva è sempre dentro la cella Point3d ptInters ; - //int nEdge2 ; - if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) { - //nEdge = 0 ; - // lato sopra - clEdge.Set( ptTR, ptTl) ; - // lato sinistro - if ( ptEnd.x < ptBL.x) { - //nEdge2 = 1 ; - clEdge2.Set( ptTl, ptBL) ; - } - } - else if ( ptEnd.x <= ptBL.x && ptEnd.y <= ptTR.y) { - nEdge = 1 ; - // lato sinistro - clEdge.Set( ptTl, ptBL) ; - // lato sotto - if ( ptEnd.y < ptBL.y) { - //nEdge2 = 2 ; - clEdge2.Set( ptBL, ptBr) ; - } - } - else if ( ptEnd.y <= ptBL.y && ptEnd.x >= ptBL.x) { - nEdge = 2 ; - // lato sotto - clEdge.Set( ptBL, ptBr) ; - // lato destro - if ( ptEnd.x > ptTR.x) { - //nEdge2 = 3 ; - clEdge2.Set( ptBr, ptTR) ; - } - } - else if ( ptEnd.x >= ptTR.x && ptEnd.y >= ptBL.y) { - nEdge = 3 ; - // lato desto - clEdge.Set( ptBr, ptTR) ; - // lato sopra - if ( ptEnd.y > ptTR.y) { - //nEdge2 = 0 ; - clEdge2.Set( ptTR, ptTl) ; - } - } - else - return false ; - bool bIntersFound = false ; - // intersezione e controlli - IntersLineLine illExit( clTrim, clEdge, true) ; - IntCrvCrvInfo aInfo, aInfo2 ; - if ( ! illExit.GetIntCrvCrvInfo( aInfo)) { - bIntersFound = false ; - if ( ! clEdge2.IsValid()) - return false ; + //CurveLine clEdge , clEdge2 ; + //Point3d ptStart , ptEnd ; + //clTrim.GetStartPoint( ptStart) ; + //clTrim.GetEndPoint( ptEnd) ; + //// trovo da quale lato sto uscendo + ////int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario + //// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario + //// -1 se la curva è sempre dentro la cella + ////int nEdge2 ; + //if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) { + // //nEdge = 0 ; + // // lato sopra + // clEdge.Set( ptTR, ptTl) ; + // // lato sinistro + // if ( ptEnd.x < ptBL.x) { + // //nEdge2 = 1 ; + // clEdge2.Set( ptTl, ptBL) ; + // } + //} + //else if ( ptEnd.x <= ptBL.x && ptEnd.y <= ptTR.y) { + // nEdge = 1 ; + // // lato sinistro + // clEdge.Set( ptTl, ptBL) ; + // // lato sotto + // if ( ptEnd.y < ptBL.y) { + // //nEdge2 = 2 ; + // clEdge2.Set( ptBL, ptBr) ; + // } + //} + //else if ( ptEnd.y <= ptBL.y && ptEnd.x >= ptBL.x) { + // nEdge = 2 ; + // // lato sotto + // clEdge.Set( ptBL, ptBr) ; + // // lato destro + // if ( ptEnd.x > ptTR.x) { + // //nEdge2 = 3 ; + // clEdge2.Set( ptBr, ptTR) ; + // } + //} + //else if ( ptEnd.x >= ptTR.x && ptEnd.y >= ptBL.y) { + // nEdge = 3 ; + // // lato desto + // clEdge.Set( ptBr, ptTR) ; + // // lato sopra + // if ( ptEnd.y > ptTR.y) { + // //nEdge2 = 0 ; + // clEdge2.Set( ptTR, ptTl) ; + // } + //} + //else + // return false ; + + //bool bIntersFound = false ; + //// intersezione e controlli + //IntersLineLine illExit( clTrim, clEdge, true) ; + //IntCrvCrvInfo aInfo, aInfo2 ; + //if ( ! illExit.GetIntCrvCrvInfo( aInfo)) { + // bIntersFound = false ; + // if ( ! clEdge2.IsValid()) + // return false ; + //} + //else { + // bIntersFound = true ; + // if ( aInfo.bOverlap) + // ptInters = aInfo.IciA[1].ptI ; + // else + // ptInters = aInfo.IciA[0].ptI ; + //} + //if ( clEdge2.IsValid() && ! bIntersFound){ + // IntersLineLine illExit2( clTrim, clEdge2, true) ; + // // verifico su quale dei due lati ho l'intersezione + // if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)) + // bIntersFound = false ; + // else { + // bIntersFound = true ; + // //// solo intersezione sul lato 2 + // if ( aInfo2.bOverlap) + // ptInters = aInfo2.IciA[1].ptI ; + // else + // ptInters = aInfo2.IciA[0].ptI ; + // } + //} + //if ( ! bIntersFound) + // return false ; + + PtrOwner pCC( CreateCurveComposite()) ; + PolyLine plSimplePolygon ; + plSimplePolygon = plPolygon ; + plSimplePolygon.RemoveAlignedPoints() ; + pCC->FromPolyLine( plSimplePolygon) ; + IntersCurveCurve icc( clTrim, *pCC) ; + IntCrvCrvInfo iccInfo ; + if ( icc.GetOverlaps()) { + for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) { + icc.GetIntCrvCrvInfo( i, iccInfo) ; + if( iccInfo.bOverlap){ + ptInters = iccInfo.IciA[1].ptI ; + break ; + } + } } else { - bIntersFound = true ; - if ( aInfo.bOverlap) - ptInters = aInfo.IciA[1].ptI ; - else - ptInters = aInfo.IciA[0].ptI ; + int nLastInters = icc.GetIntersCount() -1 ; + icc.GetIntCrvCrvInfo( nLastInters, iccInfo) ; + ptInters = iccInfo.IciA[0].ptI ; } - if ( clEdge2.IsValid() && ! bIntersFound){ - IntersLineLine illExit2( clTrim, clEdge2, true) ; - // verifico su quale dei due lati ho l'intersezione - if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)) - bIntersFound = false ; - else { - bIntersFound = true ; - //// solo intersezione sul lato 2 - if ( aInfo2.bOverlap) - ptInters = aInfo2.IciA[1].ptI ; - else - ptInters = aInfo2.IciA[0].ptI ; - } - } - if ( ! bIntersFound) - return false ; + // determino il lato/vertice di uscita OnWhichEdge( nId, ptInters, nEdge) ; m_mTree[nId].m_vInters.back().nOut = nEdge ; @@ -2945,24 +2995,41 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool //---------------------------------------------------------------------------- bool -Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) +Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, + const PolyLine& plCell, const PolyLine& plCell3d) { // conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato int nId = m_vnLeaves[nLeafId] ; PNTMATRIX vEdgeVertex(4) ; PNTMATRIX vEdgeVertex3d(4) ; - vEdgeVertex[0].push_back( m_mTree[nId].GetTopRight()) ; - vEdgeVertex[1].push_back( m_mTree[nId].GetTopLeft()) ; - vEdgeVertex[2].push_back( m_mTree[nId].GetBottomLeft()) ; - vEdgeVertex[3].push_back( m_mTree[nId].GetBottomRight()) ; + Point3d ptBL = m_mTree[nId].GetBottomLeft() ; + Point3d ptTR = m_mTree[nId].GetTopRight() ; + Point3d ptTl = m_mTree[nId].GetTopLeft() ; + Point3d ptBr = m_mTree[nId].GetBottomRight() ; + int nVertToErase = m_mTree.at(nId).m_nVertToErase ; + if( nVertToErase != 2) + vEdgeVertex[0].push_back( ptTR) ; + if( nVertToErase != 3) + vEdgeVertex[1].push_back( ptTl) ; + if( nVertToErase != 0) + vEdgeVertex[2].push_back( ptBL) ; + if( nVertToErase != 1) + vEdgeVertex[3].push_back( ptBr) ; // capisco se sono in modalità ForTriangulation bool bForTriangulation = plCell3d.GetPointNbr() != 0 ; if ( bForTriangulation) { - vEdgeVertex3d[0].push_back( m_mVert[nId][2]) ; - vEdgeVertex3d[1].push_back( m_mVert[nId][3]) ; - vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ; - vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ; + if( nVertToErase != 2) + vEdgeVertex3d[0].push_back( m_mVert[nId][2]) ; + if( nVertToErase != 3) + vEdgeVertex3d[1].push_back( m_mVert[nId][3]) ; + if( nVertToErase != 0) + vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ; + if( nVertToErase != 1) + vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ; } + + + // la PolyLine è riempita a partire dal lato bottom Point3d ptStart, pt3d ; plCell.GetFirstPoint( ptStart) ; @@ -2975,7 +3042,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX if ( j == 3) next = 0 ; Point3d ptToAdd ; - while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, vEdgeVertex[next][0])) { + Point3d ptNextVert ; + switch ( next ) { + case 0 : ptNextVert = ptTR ; break ; + case 1 : ptNextVert = ptTl; break ; + case 2 : ptNextVert = ptBL ; break ; + case 3 : ptNextVert = ptBr ; break ; + } + while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) { vEdgeVertex[j].push_back( ptToAdd) ; if ( bForTriangulation) { plCell3d.GetNextPoint( pt3d) ; @@ -3101,13 +3175,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX while ( ! ( bValidNextStart && bAtNextStart) && bNotCameBack) { Point3d ptVert ; if ( nEdge == 0) - ptVert = vEdgeVertex[1][0] ; + ptVert = ptTl ; else if ( nEdge == 1) - ptVert = vEdgeVertex[2][0] ; + ptVert = ptBL ; else if ( nEdge == 2) - ptVert = vEdgeVertex[3][0] ; + ptVert = ptBr ; else if ( nEdge == 3) - ptVert = vEdgeVertex[0][0] ; + ptVert = ptTR ; AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; @@ -3155,13 +3229,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX while ( bNotCameBack) { Point3d ptVert ; if ( nEdge == 0) - ptVert = vEdgeVertex[1][0] ; + ptVert = ptTl ; else if ( nEdge == 1) - ptVert = vEdgeVertex[2][0] ; + ptVert = ptBL ; else if ( nEdge == 2) - ptVert = vEdgeVertex[3][0] ; + ptVert = ptBr ; else if ( nEdge == 3) - ptVert = vEdgeVertex[0][0] ; + ptVert = ptTR ; AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; @@ -3521,10 +3595,10 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; return true ; } - Point3d ptBr = vEdgeVertex[3][0] ; - Point3d ptTR = vEdgeVertex[0][0] ; - Point3d ptTl = vEdgeVertex[1][0] ; - Point3d ptBL = vEdgeVertex[2][0] ; + Point3d ptBr = m_mTree.at(nId).GetBottomRight() ; + Point3d ptTR = m_mTree.at(nId).GetTopRight() ; + Point3d ptTl = m_mTree.at(nId).GetTopLeft() ; + Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ; Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; // verifico di essere allineato con un lato, sennò aggiungo e basta @@ -3584,7 +3658,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation){ Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[1][0])) + if( ! AreSamePointApprox(ptToAdd, ptTl)) m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; else pt3d = vEdgeVertex3d[1][0] ; @@ -3606,7 +3680,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation) { Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[2][0])) + if( ! AreSamePointApprox(ptToAdd, ptBL)) m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; else pt3d = vEdgeVertex3d[2][0] ; @@ -3628,7 +3702,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation){ Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[3][0])) + if( ! AreSamePointApprox(ptToAdd, ptBr)) m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; else pt3d = vEdgeVertex3d[3][0] ; @@ -3650,7 +3724,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation) { Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, vEdgeVertex[0][0])) + if( ! AreSamePointApprox(ptToAdd, ptTR)) m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; else pt3d = vEdgeVertex3d[0][0] ; diff --git a/Tree.h b/Tree.h index 108efd4..1d0a45d 100644 --- a/Tree.h +++ b/Tree.h @@ -155,7 +155,7 @@ class Cell ~Cell( void) {} Cell( void) : m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), - m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), + m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ORIG), m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) { Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ; @@ -163,7 +163,7 @@ class Cell } Cell( const Point3d& ptBL, const Point3d& ptTR) : m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), - m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), + m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {} bool IsSame( const Cell& cOtherCell) const { return ( m_nId == cOtherCell.m_nId) ; } @@ -217,6 +217,7 @@ class Cell bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V) std::vector m_vInters ; // vettore delle intersezioni della cella con i loop di trim // ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella + int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo private : Point3d m_ptPbl ; // punto bottom left @@ -273,8 +274,8 @@ class Tree void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene - bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle - bool FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim + bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle + bool FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim // resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni. bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella From 649f97e93322884ec13b94d675407691908b6a5c Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 15 Jul 2024 10:04:48 +0200 Subject: [PATCH 43/45] EgtGeomKernel : - correzione bug di triangolazione bezier. --- Tree.cpp | 26 +++++++++++++++----------- Tree.h | 3 ++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 0b26e2a..57ef219 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -3049,10 +3049,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX case 2 : ptNextVert = ptBL ; break ; case 3 : ptNextVert = ptBr ; break ; } - while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) { - vEdgeVertex[j].push_back( ptToAdd) ; - if ( bForTriangulation) { - plCell3d.GetNextPoint( pt3d) ; + if ( ! bForTriangulation) { + while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) + vEdgeVertex[j].push_back( ptToAdd) ; + } + else { + while ( plCell.GetNextPoint( ptToAdd) && plCell3d.GetNextPoint( pt3d) && ! AreSamePointExact( ptToAdd, ptNextVert)) { + vEdgeVertex[j].push_back( ptToAdd) ; vEdgeVertex3d[j].push_back( pt3d) ; } } @@ -3090,7 +3093,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX nFirstLoopInPoly = j ; } for ( Point3d ptInt : inA.vpt) { - AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptInt, plTrimmedPoly3d) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptInt, plTrimmedPoly3d, bForTriangulation) ; } vAddedLoops.push_back( j) ; nEdge = inA.nOut ; @@ -3182,7 +3185,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX ptVert = ptBr ; else if ( nEdge == 3) ptVert = ptTR ; - AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d, bForTriangulation) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3) @@ -3202,6 +3205,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], m_mTree[nId].m_vInters[vToCheckNow[nNext]].vpt[0])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; ++ c ; } } @@ -3215,6 +3219,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; ++ c ; } } @@ -3236,7 +3241,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX ptVert = ptBr ; else if ( nEdge == 3) ptVert = ptTR ; - AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d, bForTriangulation) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3) @@ -3249,6 +3254,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; + plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; ++ c ; } } @@ -3579,11 +3585,9 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const //---------------------------------------------------------------------------- bool -Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d) const +Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, + const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool bForTriangulation) const { - //capisco se sono in modalità ForTriangulation - bool bForTriangulation = plTrimmedPoly3d.GetPointNbr() ; - // se è il primo punto della PolyLine lo aggiungo if ( plTrimmedPoly.GetPointNbr() == 0) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; diff --git a/Tree.h b/Tree.h index 1d0a45d..7d6a1e8 100644 --- a/Tree.h +++ b/Tree.h @@ -284,7 +284,8 @@ class Tree bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3) bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // sul lato nEdge controllo se ptP1 viene prima di ptP2. bool AreSameEdge( int nEdge1, int nEdge2) const ; // indica se i due edge sono lo stesso. Un vertice adiacente ad un edge viene considerato uguale a questo edge - bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto + bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, + const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool ForTriangulation) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto bool SetRightEdgeIn( int nId) ; // categorizza la cella in base all'edge destro per poter poi definire m_nFlag bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata) bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW) From 9dd4e043d450d5f1e14537318c1d324512bef5e4 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 15 Jul 2024 17:05:44 +0200 Subject: [PATCH 44/45] EgtGeomKernel : - correzione bug nelle rigate con le Bezier. --- SurfBezier.cpp | 96 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 21 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index ff0588b..d855055 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -46,6 +46,8 @@ using namespace std ; //---------------------------------------------------------------------------- GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ; +static bool ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, ICurveComposite* pCrvU1) ; + //---------------------------------------------------------------------------- SurfBezier::SurfBezier( void) : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false), @@ -3846,7 +3848,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int for ( int i = 0 ; i < nDegU + 1 ; ++i ) { if( i != nDegU && !( i == 0 && k == 0)) continue ; - Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; // il caso razionale come è da gestire????? devo usare i punti omogenei per il calcolo delle distanze?? + Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; if ( bRat0) vdW0.push_back( pSubCrv0->GetControlWeight( i)) ; // aggiungo alla polyline solo gli estremi delle sottocurve ( senza ripetizioni) @@ -3883,27 +3885,31 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bool bRat = bRat0 && bRat1 ; int nSecondRowInd = nDegU * nSpanU + 1 ; + // se sono chiuse devo controllare che gli start siano il più allineati possibile, se non lo sono cambio gli start + ChangeStartForClosed( plU0, plU1, pCrvU0, pCrvU1) ; + // se sto usando la ISOPARM o la MINDIST semplice allora collego più span di una curva allo stesso punto - // ( aggiungo delle span alla curva che localmente ne ha di meno, semplicemente riprendo più volte lo stesso punto) if ( nRuledType == RLT_B_MINDIST) { // creo le liste di punti per le isoparametriche in U PNTIVECTOR vPnt0Match, vPnt1Match ; bool bCommonPoint = false ; - AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; + AssociatePolyLinesMinDistPoints( plU0, plU1, vPnt0Match, vPnt1Match, bCommonPoint) ; // devo contare il numero di ripetizioni dei match nel mezzo delle curve, perché aumentano il numero di span della superficie!! int nRep0 = 0 ; int nIndMatch = 0 ; int nIndMatchNext = 0 ; + int nRep1 = int( vPnt1Match.size() - 1) - vPnt0Match.back().second ; for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { nIndMatch = vPnt0Match[i].second ; nIndMatchNext = vPnt0Match[i+1].second ; if ( nIndMatch != nIndMatchNext) - nRep0 += nIndMatchNext - nIndMatch - 1; + nRep1 += nIndMatchNext - nIndMatch - 1 ; + if ( nIndMatch == nIndMatchNext) + ++nRep0 ; } - int nRep1 = int( vPnt1Match.size() - 1) - vPnt0Match.back().second ; // reinizializzo la superficie con il nuovo numero di span in U - nSpanU = nSpanU0 + nRep0 + nRep1 ; + nSpanU = nSpanU0 + nRep1 ; if ( nSpanU < max(nSpanU0, nSpanU1)) nSpanU = max(nSpanU0, nSpanU1) ; nSecondRowInd = nDegU * nSpanU + 1 ; @@ -3913,7 +3919,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nCount0 = 0 ; nCount1 = 0 ; - // scorro gli estremi delle sottocurve della curva 1 + // scorro gli estremi delle sottocurve della curva U0 for ( int i = 0 ; i < int( vPnt0Match.size() - 1) ; ++i) { nIndMatch = vPnt0Match[i].second ; nIndMatchNext = vPnt0Match[i+1].second ; @@ -3927,8 +3933,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( j), pSubCrv0->GetControlWeight( j)) ; } ++ nCount0 ; - // ripeto l'ultimo punto aggiunto alla riga 2 - int nInd = nIndMatch - 1 ; + // ripeto l'ultimo punto aggiunto alla riga U1 della superificie + int nInd = nIndMatch > 0 ? nIndMatch - 1 : 0 ; const ICurveBezier* pSubCrv0 = GetCurveBezier( pCrvU1->GetCurve( nInd)) ; for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { int nPoint = nCount1 == 0 ? 0 : nDegU ; @@ -3938,7 +3944,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int SetControlPoint( nSecondRowInd + nCount1 * nDegU + j, pSubCrv0->GetControlPoint( nPoint), pSubCrv0->GetControlWeight( nPoint)) ; } ++nCount1 ; - } + } else { // qui devo capire se aggiungere la nuova sottocurva prima o dopo la ripetizione dei punti // se il match del punto della U1 è uguale al punto a cui ero arrivato sulla U0 allora prima aggiungo la ripetizione di punti @@ -4146,7 +4152,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } // spezzo le curve di bezier dove è necessario aggiungere dei punti - else if ( nRuledType == RLT_B_MINDIST_PLUS ) { // probabilmente se questo funziona bene non serve la modilità ISOPARM_SMOOTH + else if ( nRuledType == RLT_B_MINDIST_PLUS ) { // scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva // in quel punto la curva verrà spezzata, a meno che non si trovi una joint già sufficientemente vicina @@ -4333,7 +4339,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int switch( vnAddedOrNextIsRep0[z]) { case 0 : if( vbRep1[nSplit]) ++ nRep1 ; - vbRep1.insert( vbRep1.begin() + nSplit, vbRep1[nSplit]) ; break ; // di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo + // di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo + vbRep1.insert( vbRep1.begin() + nSplit, vbRep1[nSplit]) ; break ; case 1 : vbRep1.insert( vbRep1.begin() + nSplit, true) ; break ; case 2 : if ( vbRep1[nSplit]) --nRep1 ; @@ -4357,7 +4364,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int switch( vnAddedOrNextIsRep1[z]) { case 0 : if( vbRep0[nSplit]) ++ nRep0 ; - vbRep0.insert( vbRep0.begin() + nSplit, vbRep0[nSplit]) ; break ; // di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo + // di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo + vbRep0.insert( vbRep0.begin() + nSplit, vbRep0[nSplit]) ; break ; case 1 : vbRep0.insert( vbRep0.begin() + nSplit, true) ; break ; case 2 : if( vbRep0[nSplit]) -- nRep0 ; @@ -4388,21 +4396,23 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int -- nRep0 ; -- nRep1 ; } - if ( ! bRep0) + if ( ! bRep0 || nCrv1 == nSpanU1 - 1) ++ nCrv1 ; - if ( ! bRep1) + if ( ! bRep1 || nCrv0 == nSpanU0 - 1) ++ nCrv0 ; ++nAddedSpan ; } // se non sono arrivato all'ultima curva su U0 o U1 vuol dire che ho creato delle ripetizioni che non ho contato prima - if( nCrv1 < nSpanU1) + if( nCrv1 < nSpanU1) { nRep1 += nSpanU1 - nCrv1 ; - for ( int z = int( vbRep1.size() - 1) ; z >= nCrv1 ; --z) - vbRep1[z] = true ; - if( nCrv0 < nSpanU0) + for ( int z = int( vbRep1.size() - 1) ; z >= nCrv1 ; --z) + vbRep1[z] = true ; + } + if( nCrv0 < nSpanU0) { nRep0 += nSpanU0 - nCrv0 ; - for ( int z = int( vbRep0.size() - 1) ; z >= nCrv0 ; --z) - vbRep0[z] = true ; + for ( int z = int( vbRep0.size() - 1) ; z >= nCrv0 ; --z) + vbRep0[z] = true ; + } // trovo il numero di span che dovrà avere la superficie // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) @@ -4557,3 +4567,47 @@ SurfBezier::ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveCompos // } // return true ; //} + +static bool ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, ICurveComposite* pCrvU1) { + // se sono chiuse devo controllare che gli start siano il più allineati possibile, se non lo sono cambio gli start + if ( plU0.IsClosed() && plU1.IsClosed()) { + vector> vDistVert ; + tuple tMatch ; + Point3d pt0 ; + bool bOk0 = plU0.GetFirstPoint( pt0) ; + int c0 = 0 ; + double dMinDist = INFINITO ; + while ( bOk0) { + Point3d pt1 ; + bool bOk1 = plU1.GetFirstPoint( pt1) ; + int c1 = 0 ; + while ( bOk1) { + double dDist = Dist( pt0, pt1) ; + if ( dDist < dMinDist) { + tMatch = make_tuple( dDist, c0, pt0, c1, pt1) ; + dMinDist = dDist ; + } + ++c1 ; + bOk1 = plU1.GetNextPoint( pt1) ; + } + vDistVert.push_back( tMatch) ; + dMinDist = INFINITO ; + c1 = 0 ; + ++c0 ; + bOk0 = plU0.GetNextPoint( pt0) ; + } + int nMin = 0 ; + dMinDist = INFINITO ; + for ( int i = 0 ; i < int( vDistVert.size()) ; ++i) { + if( get<0>(vDistVert[i]) < dMinDist) { + dMinDist = get<0>(vDistVert[i]) ; + nMin = i ; + } + } + ChangePolyLineStart(plU0, get<2>(vDistVert[nMin]), EPS_SMALL) ; + ChangePolyLineStart(plU1, get<4>(vDistVert[nMin]), EPS_SMALL) ; + pCrvU0->ChangeStartPoint( double( get<1>(vDistVert[nMin]))) ; + pCrvU1->ChangeStartPoint( double( get<3>(vDistVert[nMin]))) ; + } + return true ; +} From b9138029dbe30a6e09e288e7f2047be6e8885ec2 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 15 Jul 2024 17:34:11 +0200 Subject: [PATCH 45/45] EgtGeomKernel 2.6g3 : - aggionamento versione. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 06e49bd091f36b02e7319716684d7caf66bc1c88..11258eabd423711fc8d2dc29016137c3e926e7b1 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SD&&FAG5nSs