//---------------------------------------------------------------------------- // 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/EGkDistPointLine.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 ; //------------------------------------------------------------------------------- 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 ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) { // verifica parametri if ( &vpCurve == nullptr || vpCurve.empty()) return nullptr ; // calcolo le polilinee che approssimano le curve della regione POLYLINEVECTOR vPL ; vPL.resize( vpCurve.size()) ; for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) { if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i])) return nullptr ; } Vector3d vtN ; INTMATRIX vnPLIndMat ; BOOLVECTOR vbInvert ; if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat,vbInvert)) return nullptr ; POLYLINEVECTOR vPLOrd ; for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) { for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){ vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ; if ( vbInvert[vnPLIndMat[i][j]]) vPLOrd.back().Invert() ; } } // creo e setto la superficie di bezier PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByRegion( vPLOrd)) return nullptr ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bCapEnds, double dLinTol) { // verifica parametri if ( pCurve == nullptr || &vtExtr == nullptr) return nullptr ; PtrOwner pBezierForm( CurveToBezierCurve( pCurve)) ; // creo e setto la superficie di Bezier PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr)) return nullptr ; // restituisco la superficie return Release( pSbz) ; } ////------------------------------------------------------------------------------- //ISurfCompo* //GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) ///// RICHIEDE LE SURF COMPO///////////////// //{ // // verifica parametri // if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr) // return nullptr ; // // se una sola curva, uso la funzione precedente // if ( vpCurve.size() == 1 ) // return GetSurfBezierByExtrusion( 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 pSbz1( CreateBasicSurfBezier()) ; // if ( IsNull( pSbz1) || ! pSbz1->CreateByRegion( vPL)) // return nullptr ; // // creo la seconda superficie come copia della prima e poi inverto la prima // PtrOwner pSbz2( pSbz1->Clone()) ; // pSbz1->Invert() ; // // // creo e unisco le diverse superfici di estrusione // for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { // // estrusione // SurfBezier SbzLat ; // if ( ! SbzLat.CreateByExtrusion( vPL[i], vtExtr)) // qui mi serve la curva e non la polyline della curva. vuol dire che dalla CalcRegionPolyLines devo farmi restituire anche le curve ordinate // return nullptr ; // } // // restituisco la superficie // return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica //} //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // con l'aggiunta delle SURFCOMPO posso gestire anche i cap e curve che attraversano l'asse { // verifica parametri if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) return nullptr ; // limite minimo su tolleranza dLinTol = max( dLinTol, EPS_SMALL) ; // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, ANG_FULL, 0)) return nullptr ; // se superficie risultante chiusa, verifico che la normale sia verso l'esterno double dVol ; if ( pSbz->GetVolume( dVol) && dVol < 0) pSbz->Invert() ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) { // verifica parametri if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) return nullptr ; // limite minimo su tolleranza dLinTol = max( dLinTol, EPS_SMALL) ; // creo e setto la superficie bezier PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove)) return nullptr ; // se superficie risultante chiusa, verifico che la normale sia verso l'esterno double dVol ; if ( pSbz->GetVolume( dVol) && dVol < 0) pSbz->Invert() ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol) { // riferimento all'inizio della linea guida Frame3d frStart ; Point3d ptStart ; pGuide->GetStartPoint( ptStart) ; Vector3d vtStart ; pGuide->GetStartDir( vtStart) ; //frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; // capisco se la guida è una linea spezzata o una curva bool bGuideIsPolyLine = false ; switch ( pGuide->GetType()) { case CRV_COMPO : { bGuideIsPolyLine = true ; const ICurveComposite* pCC = GetCurveComposite( pGuide) ; for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; if ( pCrv->GetType() != CRV_LINE) { if ( pCrv->GetType() == CRV_BEZIER) { const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ; bGuideIsPolyLine = pCrvBez->IsALine() ; } else bGuideIsPolyLine = false ; } } break ; } case CRV_LINE : bGuideIsPolyLine = true ; break ; case CRV_BEZIER : { // controllo se i punti di controllo sono allineati const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ; bGuideIsPolyLine = pCrvBez->IsALine() ; break ; } default : break ; } bool bRat = false ; int nSpanV = 0 ; PtrOwner pCrvV( CreateCurveComposite()) ; if ( bGuideIsPolyLine ) { if ( pGuide->GetType() == CRV_LINE) nSpanV = 1 ; else if ( pGuide->GetType() == CRV_COMPO) nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ; } else { //converto in bezier la guida ( grado 3, non razionale) if ( pGuide->GetType() != CRV_BEZIER) pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ; else { const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ; if ( ! pGuideBez->IsRational()) pCrvV->AddCurve( pGuide->Clone()) ; else pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ; } if ( IsNull( pCrvV) || ! pCrvV->IsValid()) return nullptr ; nSpanV = pCrvV->GetCurveCount() ; } // converto in bezier la sezione ( grado 3, non razionale) PtrOwner pCrvU( CreateCurveComposite()) ; if ( pSect->GetType() != CRV_BEZIER) pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ; else { const ICurveBezier* pSectBez = GetCurveBezier( pSect) ; pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ; } if ( IsNull( pCrvU) || ! pCrvU->IsValid()) return nullptr ; int nSpanU = int( pCrvU->GetCurveCount()) ; int nDegV = 3 ; if ( bGuideIsPolyLine) nDegV = 1 ; int nDegU = 3 ; // superficie swept PtrOwner pSurfBez( CreateSurfBezier()) ; if ( bGuideIsPolyLine) { frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; // porto la sezione nel sistema di riferimento del piano in cui giace pCrvU->ToLoc( frStart) ; // la guida è una linea spezzata, quindi posso lavorare con gli offset ICRVCOMPOPOVECTOR vCC ; INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ; int nMaxSpanV = nSpanV ; for ( int i = 0 ; i < nSpanU ; ++i) { const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ; for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) { Point3d ptCtrl = pSubCrv->GetControlPoint( j) ; // faccio l'offset della guida nel punto di controllo della sezione OffsetCurve OffsCrv ; if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0) return nullptr ; vCC.emplace_back() ; vCC.back()->AddCurve(OffsCrv.GetLongerCurve()) ; if ( IsNull( pCrvV)) return nullptr ; vCC.back()->Translate( ptCtrl.y * frStart.VersY()) ; //mRep[ i * nDegU + j].resize(vCC.back()->GetCurveCount()) ; nMaxSpanV = max ( nMaxSpanV, vCC.back()->GetCurveCount()) ; } } // devo capire quante span in V devo creare e a quale span appartengono i tratti degli offset for ( int k = 0 ; k < int( vCC.size()) ; ++k) { const ICurveComposite* pCC = vCC[k] ; mRep[k].resize( nMaxSpanV) ; for ( int z = 0 ; z < int( mRep[k].size()) ; ++z) { int nProp = - 1 ; pCC->GetCurveTempProp( z, nProp) ; if ( nProp == 0) { // ho trovato almeno una curva di offset che ha un tratto non derivante direttamente dalla curva originale // tutte le altre curve che hanno curve di offeset che non hanno questo tratto bonus dovranno ripetere il punto di controllo for ( int w = 0 ; w < int( vCC.size()) ; ++w) { const ICurveComposite* pCCOther = vCC[w] ; int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ; if ( nPropCheck != 0) mRep[w][z] = 1 ; } } } } // conto in quante colonne di mRep la somma degli elementi è != 0 // questo numero va aggiunto all'attuale nSpanV int nSpanPlus = 0 ; for ( int z = 0 ; z < nMaxSpanV ; ++z) { int nPosTot = 0 ; for ( int k = 0 ; k < int( mRep.size()) ; ++k ) nPosTot += mRep[k][z] ; if ( nPosTot != 0) nSpanPlus += 1 ; } nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ; nSpanV = nMaxSpanV ; pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; //// aggiungo i punti di controllo alla superficie //for ( int i = 0 ; i < nSpanU ; ++i) { // for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) { // const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ; // for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) { // const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ; // if ( pCL == nullptr) // return nullptr ; // if ( z == 0) { // Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ; // pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ; // } // Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ; // pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ; // } // } //} //// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO //for ( int i = 0 ; i < int( vCC.size()) ; ++i) { // const ICurveComposite* pOffsetCrv = vCC[i] ; // for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) { // const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ; // if ( pCL == nullptr) // return nullptr ; // if ( z == 0) { // Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ; // pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ; // } // Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ; // pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ; // } //} } else { pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; // VERSIONE con le copie della sezione ( superficie skinned) // creo delle copie della curva e faccio la skinned // per ogni sottocurva della guida ( che sarà composta da curve di bezier di grado 3) // posiziono una copia della curva di sezione per ogni punto di controllo frStart.Set( ptStart, vtStart) ; pCrvU->ToLoc( frStart) ; ICURVEPOVECTOR vCrvSet ; CICURVEPVECTOR vpCrv ; RotationMinimizingFrame rmfGuide ; rmfGuide.Set( pCrvV, frStart) ; //double dStep = 0.25 ; FRAME3DVECTOR vFrame ; int nSpanV = pCrvV->GetCurveCount() ; int nSplit = 8 * nSpanV ; rmfGuide.GetFramesBySplit( nSplit, vFrame) ; for ( int i = 0 ; i < nSpanV ; ++i) { for ( int j = i==0 ? 0 : 1 ; j < nSplit + 1 ; ++j) { ICurve* pNewSect = pCrvU->Clone() ; pNewSect->ToGlob( vFrame[j]) ; // da sistemare se ho più curve ( la pGuide è una compo) e in base allo step di divisione!!!!!!!!! /////// vpCrv.push_back( pNewSect) ; vCrvSet.emplace_back( pNewSect) ; } } return GetSurfBezierSkinned( vpCrv, dLinTol) ; //////VERSIONE con l'offset dei punti di controllo // richiede l'interpolazione dei punti // //// faccio l'offset della guida e poi riconverto i risultati in curve di bezier tramite interpolazione // //frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; //// porto la sezione nel sistema di riferimento del piano in cui giace //pCrvU->ToLoc( frStart) ; //for ( int i = 0 ; i < nSpanU ; ++i) { // const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ; // for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) { // Point3d ptCtrl = pSubCrv->GetControlPoint( j) ; // // faccio l'offset della guida nel punto di controllo della sezione // OffsetCurve OffsCrv ; // if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0) // return nullptr ; // PtrOwner pCrvV( CreateCurveComposite()) ; // pCrvV->AddCurve( OffsCrv.GetLongerCurve()) ; // if ( IsNull( pCrvV)) // return nullptr ; // pCrvV->Translate( ptCtrl.y * frStart.VersY()) ; // PNTVECTOR vPnt ; // int nOffCrvs = pCrvV->GetCurveCount() ; // for ( int z = 0 ; z < nOffCrvs ; ++z) { // Point3d ptCtrl ; // if ( z == 0) { // pCrvV->GetCurve(z)->GetStartPoint( ptCtrl) ; // vPnt.push_back( ptCtrl) ; // } // pCrvV->GetCurve(z)->GetEndPoint( ptCtrl) ; // vPnt.push_back( ptCtrl) ; // } // pCrvV.Set( CreateCurveComposite()) ; // pCrvV->AddCurve( InterpolatePointSetWithBezier( vPnt, dLinTol)) ; // // // nSpanV = pCrvV->GetCurveCount() ; // pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; /// NON POSSO REINIZIALIZZARE LA SURF QUI! // /// QUANDO INIZIO A INSERIRE I PUNTI DI CONTROLLO DEVO AVER DEFINITO nSpanV // // // // aggiungo i punti di controllo alla superficie // for ( int z = 0 ; z < nSpanV ; ++z) { // const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ; // if ( pCrvBez == nullptr) // return nullptr ; // for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) { // Point3d ptCtrl = pCrvBez->GetControlPoint( k) ; // pSurfBez->SetControlPoint( i * nDegU + j, z * nDegV + k, ptCtrl) ; // } // } // } //} } ////// se richiesti caps e sezione chiusa e guida aperta /// in attesa della SurfCompo, al momento viene fatto nell'executor //if ( bCapEnds && bSectClosed && ! bGuideClosed) { // // verifico che le due estremità siano chiuse e piatte //} // restituisco la superficie return Release( pSurfBez) ; } //------------------------------------------------------------------------------- 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 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 ; } // capisco se la guida è una linea spezzata o una curva bool bGuideIsPolyLine = false ; switch( pGuide->GetType()) { case CRV_COMPO : { bGuideIsPolyLine = true ; const ICurveComposite* pCC = GetCurveComposite( pGuide) ; for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; if ( pCrv->GetType() != CRV_LINE) { if ( pCrv->GetType() == CRV_BEZIER) { const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ; bGuideIsPolyLine = pCrvBez->IsALine() ; } else bGuideIsPolyLine = false ; } } break ; } case CRV_LINE : bGuideIsPolyLine = true ; break ; case CRV_BEZIER : { // controllo se i punti di controllo sono allineati const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ; bGuideIsPolyLine = pCrvBez->IsALine() ; break ; } default : break ; } bool bRat = false ; int nSpanV = 0 ; PtrOwner pCrvV( CreateCurveComposite()) ; if ( bGuideIsPolyLine) { if ( pGuide->GetType() == CRV_LINE) nSpanV = 1 ; else if ( pGuide->GetType() == CRV_COMPO) nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ; } else { // converto in bezier la guida ( grado 3, non razionale) if ( pGuide->GetType() != CRV_BEZIER) pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ; else { const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ; if ( ! pGuideBez->IsRational()) pCrvV->AddCurve( pGuide->Clone()) ; else pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ; } if ( IsNull( pCrvV) || ! pCrvV->IsValid()) return nullptr ; nSpanV = pCrvV->GetCurveCount() ; } // converto in bezier la sezione ( grado 3, non razionale) PtrOwner pCrvU( CreateCurveComposite()) ; if ( pSect->GetType() != CRV_BEZIER) pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ; else { const ICurveBezier* pSectBez = GetCurveBezier( pSect) ; if ( ! pSectBez->IsRational()) pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! else pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ; } if ( IsNull( pCrvU) || ! pCrvU->IsValid()) return nullptr ; // calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita FRAME3DVECTOR vFrames ; if ( bRMF) { RotationMinimizingFrame RMF ; if ( bGuideIsPolyLine) { if ( ! RMF.Set( pGuide, frStart) || ! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty()) return nullptr ; } else { if ( ! RMF.Set( pGuide, frStart) || ! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty()) return nullptr ; } } else { RotationXplaneFrame RXF ; if ( bGuideIsPolyLine) { if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) || ! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty()) return nullptr ; } else { if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) || ! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty()) return nullptr ; } } // per ogni Frame calcolato, la sezione va roto-traslata lungo la guida int nSpanU = int( pCrvU->GetCurveCount()) ; int nDegU = 9 ; // debug int nDegV = 3 ; if ( bGuideIsPolyLine){ nDegV = 1 ; // superficie swept PtrOwner pSurfBez( CreateSurfBezier()) ; pSurfBez->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; pCrvU->ToLoc( frStart) ; for ( int f = 0 ; f < int( vFrames.size()) ; ++f) { PtrOwner pNewSect( pCrvU->Clone()) ; pNewSect->ToGlob( vFrames[f]) ; for ( int i = 0 ; i < nSpanU ; ++i) { const ICurveBezier* pSubCrvBez = GetCurveBezier( pNewSect->GetCurve( i)) ; for ( int j = 0 ; j < nDegU + 1 ; ++j) { Point3d ptCtrl = pSubCrvBez->GetControlPoint( j) ; pSurfBez->SetControlPoint( i * nDegU + j, f, ptCtrl) ; } } } return Release( pSurfBez) ; } else { // porto la sezione nel sistema di riferimento del piano in cui giace pCrvU->ToLoc( frStart) ; ICURVEPOVECTOR vCrvSet ; CICURVEPVECTOR vpCrv ; for ( int f = 0 ; f < int( vFrames.size()) ; ++f) { ICurve* pNewSect = pCrvU->Clone() ; // porto la curva nel frame corrente pNewSect->ToGlob( vFrames[f]) ; vpCrv.push_back( pNewSect) ; vCrvSet.emplace_back( pNewSect) ; } return GetSurfBezierSkinned( vpCrv, dLinTol) ; } //// 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) ; //} //// 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 nullptr ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol) { // verifica parametri if ( &ptP == nullptr || pCurve == nullptr) return nullptr ; // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve)) return nullptr ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol) { // verifica parametri if ( pCurve1 == nullptr || pCurve2 == nullptr) return nullptr ; // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC1( CreateCurveComposite()) ; if ( pCurve1->GetType() != CRV_BEZIER) pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ; else pCC1->AddCurve( pCurve1->Clone()) ; if ( IsNull( pCC1) || ! pCC1->IsValid()) return nullptr ; // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC2( CreateCurveComposite()) ; if ( pCurve2->GetType() != CRV_BEZIER) pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ; else pCC2->AddCurve( pCurve2->Clone()) ; if ( IsNull( pCC2) || ! pCC2->IsValid()) return nullptr ; // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType)) return nullptr ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv, const INTVECTOR& vShown, const INTINTVECTOR& vNewOrEdited, double dLinTol) { // verifica parametri if ( pCurve1 == nullptr || pCurve2 == nullptr) return nullptr ; // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC1( CreateCurveComposite()) ; if ( pCurve1->GetType() != CRV_BEZIER) pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ; else pCC1->AddCurve( pCurve1->Clone()) ; if ( IsNull( pCC1) || ! pCC1->IsValid()) return nullptr ; // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC2( CreateCurveComposite()) ; if ( pCurve2->GetType() != CRV_BEZIER) pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ; else pCC2->AddCurve( pCurve2->Clone()) ; if ( IsNull( pCC2) || ! pCC2->IsValid()) return nullptr ; // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv, vNewCrv, vShown, vNewOrEdited)) return nullptr ; // restituisco la superficie return Release( pSbz) ; } //------------------------------------------------------------------------------- ISurfBezier* GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol) { // verifico che le curve siano valide for ( int i = 0 ; i < int( vCrv.size()) ; ++i) { if ( vCrv[i] == nullptr || ! vCrv[i]->IsValid()) return nullptr ; } // se ho solo due curve allora faccio la rigata if ( vCrv.size() == 2) return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ; //trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier // se la curva è già una bezier singola la tengo, sennò la converto ICURVEPOVECTOR vCrvBez ; for ( int c = 0 ; c < int( vCrv.size()) ; ++c){ PtrOwner pCC( CreateCurveComposite()) ; if ( vCrv[c]->GetType() != CRV_BEZIER ) pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ; else pCC->AddCurve( vCrv[c]->Clone()) ; if ( IsNull( pCC) || ! pCC->IsValid()) return nullptr ; vCrvBez.emplace_back( Release( pCC)) ; } // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; if ( IsNull( pSbz) || ! pSbz->CreateBySetOfCurves( vCrvBez, true)) return nullptr ; // restituisco la superficie return Release( pSbz) ; }