From 5f56152a8b715464bd7fb712f983effef4b1f781 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 9 May 2024 15:13:25 +0200 Subject: [PATCH] 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 ;