From 247849d112ecc926de6a1be7930d12a5fc1f1070 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 21 May 2024 15:42:57 +0200 Subject: [PATCH] EgtGeomKernel : - aggiunta la funzione per modificare un singolo peso ad una curva di Bezier. - aggiunta la funzione per lo screwing con una superficie di Bezier. - aggiunto un commento. --- CurveBezier.cpp | 26 ++++++++ CurveBezier.h | 1 + SbzFromCurves.cpp | 14 ++-- SurfBezier.cpp | 163 +++++++++++++++++++++++++++++++++------------- SurfBezier.h | 2 +- SurfTriMesh.cpp | 4 ++ 6 files changed, 157 insertions(+), 53 deletions(-) diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 8fd2aed..c891c78 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -141,6 +141,32 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) return true ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::SetControlWeight( int nInd, double dW) +{ + // verifico validità, razionalità e indice + if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg) + return false ; + + // verifico che il peso non sia nullo o negativo + if ( dW < EPS_SMALL) + return false ; + + // assegno il valore e il peso + m_vWeCtrl[nInd] = dW ; + + // annullo analisi presenza singolarità + m_dParSing = - 2 ; + + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + return true ; +} + //---------------------------------------------------------------------------- bool CurveBezier::FromArc( const ICurveArc& crArc) diff --git a/CurveBezier.h b/CurveBezier.h index e51780a..dfc33fc 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -137,6 +137,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW bool Init( int nDeg, bool bIsRational) override ; bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ; bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ; + bool SetControlWeight( int nInd, double dW) override ; bool FromArc( const ICurveArc& crArc) override ; bool FromLine( const ICurveLine& crLine) override ; int GetDegree( void) const override diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 38d258d..95fa72f 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -254,7 +254,7 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // // restituisco la superficie // return Release( pSbz) ; //} -// + //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, @@ -270,11 +270,11 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) return nullptr ; - // calcolo lo step di rotazione - double dMaxRad = 0 ; - if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) - return nullptr ; - double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; + //// calcolo lo step di rotazione + //double dMaxRad = 0 ; + //if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL) + // return nullptr ; + //double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; //// se superficie rototraslata, necessari limiti sulla lunghezza dei segmenti //if ( abs( dAngRotDeg) > EPS_ANG_SMALL && abs( dMove) > EPS_SMALL){ // double dLenMax = 2.5 * abs( dMove * dStepRotDeg / dAngRotDeg) ; @@ -283,7 +283,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector //} // creo e setto la superficie bezier PtrOwner pSbz( CreateBasicSurfBezier()) ; - if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dStepRotDeg, dMove)) + if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove)) return nullptr ; //// se richiesti caps /// richiede la SurfCompo //if ( bCapEnds) { diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 831ce40..bf8e070 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -23,6 +23,7 @@ #include "Tree.h" #include "Triangulate.h" #include "SurfTriMesh.h" +#include "DistPointLine.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkStringUtils3d.h" @@ -3440,7 +3441,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr, bool //---------------------------------------------------------------------------- bool -SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dStepRotDeg, double dMove) +SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) { // verifico che l'asse di rotazione sia non nullo if ( vtAx.IsSmall()) @@ -3452,35 +3453,7 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V return false ; if ( bOnlyRev && abs( dAngRotDeg) > ANG_FULL) dAngRotDeg = _copysign( ANG_FULL, dAngRotDeg) ; - // verifico se rotazione completa - bool bFullRev = bOnlyRev && ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL) ; - - - //// aggiusto il valore dell'angolo di step /// mi serve lo step??? - //const double MIN_STEP_ROT = 1 ; - //const double MAX_STEP_ROT = 90 ; - //if ( abs( dStepRotDeg) < MIN_STEP_ROT) - // dStepRotDeg = _copysign( MIN_STEP_ROT, dAngRotDeg) ; - //else if ( abs( dStepRotDeg) > MAX_STEP_ROT) - // dStepRotDeg = _copysign( MAX_STEP_ROT, dAngRotDeg) ; - //else - // dStepRotDeg = _copysign( dStepRotDeg, dAngRotDeg) ; - //// calcolo il numero di step - //int nStep = int( dAngRotDeg / dStepRotDeg) ; - //nStep = max( nStep, 1) ; - // codice che suppone che la curva non tocchi l'asse di rivoluzione ( soprattutto lo start) - // creo la spirale su cui far la rail della curva ( in questo caso sarà la curva di bezier che delimita il bordo sinistro dello spazio parametrico tra il punto P00 e il punto P01) - PtrOwner pSpiral( CreateCurveArc()) ; - Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; - pSpiral->SetCPAN( ptAx, ptStart, dAngRotDeg, dMove, vtAx) ; - // converto in bezier la spirale - PtrOwner pCrvV ( CreateCurveComposite()) ; // converto in curva bezier di grado 3 perché l'arco è una spirale - pCrvV->AddCurve( ArcToBezierCurve( pSpiral,true)) ; - if ( IsNull( pCrvV) || ! pCrvV->IsValid()) - return false ; - int nSpanV = int( pCrvV->GetCurveCount()) ; - int nDegV = ( GetCurveBezier( pCrvV->GetCurve(0)))->GetDegree() ; // converto in bezier la curva iniziale PtrOwner pCrvU ( CreateCurveComposite()) ; pCrvU->AddCurve( CurveToBezierCurve( pCurve)) ; @@ -3488,27 +3461,127 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V return false ; int nSpanU = int( pCrvU->GetCurveCount()) ; int nDegU = ( GetCurveBezier( pCrvU->GetCurve(0)))->GetDegree() ; + + // creo la spirale su cui far la rail della curva ( in questo caso sarà la curva di bezier che delimita il bordo sinistro dello spazio parametrico tra il punto P00 e il punto P01) + PtrOwner pCrvV ( CreateCurveComposite()) ; + // devo trovare un punto che NON sta sull'asse per poter costruire una spirale e sapere quante span in V avrò + DBLVECTOR vdSpiralW ; + bool bFound = false ; + for ( int j = 0 ; j < nSpanU && ! bFound ; ++j) { + const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvU->GetCurve( j)) ; + for ( int i = 0 ; i < nDegU + 1 && ! bFound ; ++i) { + Point3d ptCtrlU = pSubCrvBezU->GetControlPoint( i) ; + DistPointLine dpl( ptCtrlU, ptAx, vtAx, 0, false) ; + if ( ! dpl.IsSmall()) { + PtrOwner pSpiral( CreateCurveArc()) ; + pSpiral->SetCPAN( ptAx, ptCtrlU, dAngRotDeg, dMove, vtAx) ; + // converto in bezier la spirale + pCrvV->AddCurve( ArcToBezierCurve( pSpiral,true)) ; + const ICurveBezier* pFirstBez = GetCurveBezier( pCrvV->GetCurve( 0)) ; + int nDeg = pFirstBez->GetDegree() ; // questo è 3 o 2 + for ( int k = 0 ; k < nDeg + 1 ; ++k) + vdSpiralW.push_back( pFirstBez->GetControlWeight( k)) ; + bFound = true ; + } + } + } + if ( ! bFound) + return false ; + + if ( IsNull( pCrvV) || ! pCrvV->IsValid()) + return false ; + int nSpanV = int( pCrvV->GetCurveCount()) ; + int nDegV = ( GetCurveBezier( pCrvV->GetCurve(0)))->GetDegree() ; // inizializzo la superficie bool bRat = true ; // perché nella direzione del parametro V ho sicuramente delle razioniali Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; // ora posso settare i punti di controllo // scorro le curve che compongono la spirale - Point3d ptP00 ; pCrvV->GetStartPoint( ptP00) ; - for ( int j = 0 ; j < nSpanV + 1; ++j) { - const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; - for( int z = 0 ; z < nDegV + 1 ; ++z) { - Point3d ptRef = pSubCrvBezV->GetControlPoint( z) ; - double dWRef = pSubCrvBezV->GetControlWeight( z) ; - Vector3d vtStepMove = ptRef - ptP00 ; - // scorro le curve che compongono la curva principale - for ( int k = 0 ; k < nSpanU ; ++k ) { - const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvU->GetCurve( k)) ; - // scorro i punti di controllo della sottocurva - for ( int i = 0 ; i < nDegU + 1 ; ++i) { - Point3d ptCtrl = pSubCrvBezU->GetControlPoint( i) ; - ptCtrl += vtStepMove ; - double dW = pSubCrvBezU->GetControlWeight( i) ; - SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrl, dW * dWRef) ; + Point3d ptPrev ; pCrvV->GetStartPoint( ptPrev) ; + Frame3d frRev ; frRev.Set( ptAx, vtAx) ; + PtrOwner pCrvUNew( pCrvU->Clone()) ; + Vector3d vtDirPrev = ptPrev - ptAx ; + vtDirPrev.ToLoc( frRev) ; + + // VERSIONE 1 // c'è qualcosa che non torna, probabilmente dovuto alla razionalità della spirale + //// faccio una rail della curva di base lungo la spirale + //for ( int j = 0 ; j < nSpanV ; ++j) { + // const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; + // for( int z = 0 ; z < nDegV + 1 ; ++z) { + // Point3d ptRef = pSubCrvBezV->GetControlPoint( z) ; + // double dWRef = pSubCrvBezV->GetControlWeight( z) ; + // ptRef *= dWRef ; + // Vector3d vtStepMove = ( ptRef - ptPrev) ; + // pCrvUNew->Translate( vtStepMove) ; + // // ruoto la curva base + // Vector3d vtDirNew = ptRef - ptAx ; + // vtDirNew.ToLoc( frRev) ; + // double dAng = 0 ; + // vtDirPrev.GetAngleXY( vtDirNew, dAng) ; + // pCrvUNew->Rotate( ptRef, vtAx, dAng) ; + // // scorro le curve che compongono la curva principale + // for ( int k = 0 ; k < nSpanU ; ++k ) { + // const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvUNew->GetCurve( k)) ; + // // scorro i punti di controllo della sottocurva + // for ( int i = 0 ; i < nDegU + 1 ; ++i) { + // Point3d ptCtrl = pSubCrvBezU->GetControlPoint( i) ; + // ptCtrl /= dWRef ; + // double dW = pSubCrvBezU->GetControlWeight( i) ; + // SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrl, dW * dWRef) ; + // } + // } + // vtDirPrev = vtDirNew ; + // ptPrev = ptRef ; + // } + //} + + // VERSIONE 2 // funziona + // per ogni punto di controllo della curva di base creo la spirale che rappresenta la screw di quel punto + // scorro le sottocurve della curva di base + for ( int k = 0 ; k < nSpanU ; ++k ) { + const ICurveBezier* pSubCrvBezU = GetCurveBezier( pCrvUNew->GetCurve( k)) ; + //scorro i punti di controllo + for ( int i = 0 ; i < nDegU + 1 ; ++i) { + if ( k != 0 && i == 0) + continue ; + Point3d ptCtrlU = pSubCrvBezU->GetControlPoint( i) ; + double dWU = pSubCrvBezU->GetControlWeight( i) ; + + PtrOwner pCrvV( CreateCurveComposite()) ; + // verifico se il punto di controllo sta sull'asse + // in tal caso anziché una spirale creo semplicemente una linea lungo l'asse + DistPointLine dpl( ptCtrlU, ptAx, vtAx, 0, false) ; + if ( ! dpl.IsSmall()) { + // creo la spirale e la converto in bezier + PtrOwner pSpiral( CreateCurveArc()) ; + pSpiral->SetCPAN( ptAx, ptCtrlU, dAngRotDeg, dMove, vtAx) ; + ICurve* pSpiralBezier( ArcToBezierCurve( pSpiral)) ; // converto in curva bezier di grado 3 perché l'arco è una spirale + pCrvV->AddCurve( pSpiralBezier) ; + } + else { + // creo un segmento in forma bezier con il giusto numero di span + PtrOwner pCL( CreateBasicCurveLine()) ; + pCL->Set( ptCtrlU, ptCtrlU + vtAx * dMove) ; + double dStep = 1. / nSpanV ; + for ( int j = 0 ; j < nSpanV ; ++j) { + PtrOwner pCLSingleSpan( GetCurveLine( pCL->CopyParamRange( j * dStep, ( j + 1) * dStep))) ; + PtrOwner pCrvBezForm( LineToBezierCurve( pCLSingleSpan,true)) ; + // prima di aggiungere le curve alla composito setto i pesi + for ( int z = 0 ; z < pCrvBezForm->GetDegree() + 1 ; ++z) + pCrvBezForm->SetControlWeight( z, vdSpiralW[z]) ; + pCrvV->AddCurve( Release( pCrvBezForm)) ; + } + } + + // aggiungo i punti di controllo + // scorro le sottocurve della spirale + for ( int j = 0 ; j < nSpanV ; ++j) { + const ICurveBezier* pSubCrvBezV = GetCurveBezier( pCrvV->GetCurve( j)) ; + // scorro i punti di controllo + for( int z = 0 ; z < nDegV + 1 ; ++z) { + double dWV = pSubCrvBezV->GetControlWeight( z) ; + Point3d ptCtrlV = pSubCrvBezV->GetControlPoint( z) ; + SetControlPoint( nDegU * k + i, nDegV * j + z, ptCtrlV, dWU * dWV) ; } } } diff --git a/SurfBezier.h b/SurfBezier.h index 2ff120b..c541e39 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -140,7 +140,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool CreateByFlatContour( const PolyLine& PL) override ; bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ; - bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dStepRotDeg, double dMove) ; + bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ; public : // IGeoObjRW int GetNgeId( void) const override ; diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 9075f16..147cdb9 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -2632,6 +2632,8 @@ VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vect ptPc.z = 0 ; ++ nSeg ; // verifico distanza + // se la curva è chiusa oppure è vicina all'asse ( entro EPS_SMALL), ma non ho che sono start o end ad essere sull'asse + // allora dovrò rimaneggiare la polyline if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) { if ( bClosed || ( ! ( nSeg == 1 && AreSamePointApprox( ORIG, ptPp)) && @@ -2750,10 +2752,12 @@ SurfTriMesh::CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Ve // verifico che la polilinea non attraversi l'asse di rivoluzione o lo tocchi in punti interni PolyLine MyPL = PL ; + // commented for debug if ( ! VeryfyPolylineForRevolution( MyPL, ptAx, vtAx) && ! AdjustPolylineForRevolution( MyPL, ptAx, vtAx)) { LOG_ERROR( GetEGkLogger(), "StmCreateByRevolution : polyline inside meets axis") return false ; } + // commented for debug // imposto ricalcolo m_nStatus = ERR ;