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 ;