diff --git a/EgtExch3dm.rc b/EgtExch3dm.rc index dc65dd6..9b879c7 100644 Binary files a/EgtExch3dm.rc and b/EgtExch3dm.rc differ diff --git a/Import3dm.cpp b/Import3dm.cpp index 9876de5..bc2ff88 100644 --- a/Import3dm.cpp +++ b/Import3dm.cpp @@ -31,8 +31,20 @@ #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtKeyCodes.h" +#include "/EgtDev/Include/EGkSbzFromCurves.h" //#include "/EgtDev/Include/EgtPerfCounter.h" + +#define SAVEREVOLVECURVE 0 +#define SAVEREVOLVESURF 0 +#define SAVEREVOLVETRIM 0 +#define SAVETRIMLOOP 0 + +#if SAVEREVOLVECURVE || SAVEREVOLVESURF || SAVEREVOLVETRIM || SAVETRIMLOOP +#include "/EgtDev/Include/EGkGeoVector3d.h" +#include "/EgtDev/Include/EGkGeoObjSave.h" +#endif + using namespace std ; ////---------------------------------------------------------------------------- @@ -577,7 +589,7 @@ Import3dm::ConvertCurve( const ON_Curve* onCurve) //---------------------------------------------------------------------------- ISurf* -Import3dm::ConvertSurface( const ON_Surface* onSurf) +Import3dm::ConvertSurface( const ON_Surface* onSurf, DBLVECTOR* vU, DBLVECTOR* vV) { if ( const ON_NurbsSurface* onNurbsSurface_ = ON_NurbsSurface::Cast( onSurf)) { ON_NurbsSurface onNurbsSurface( *onNurbsSurface_) ; @@ -618,6 +630,11 @@ Import3dm::ConvertSurface( const ON_Surface* onSurf) if ( sNurbsSurf.bPeriodicU || sNurbsSurf.bPeriodicV || ! sNurbsSurf.bClampedU || ! sNurbsSurf.bClampedV) NurbsSurfaceCanonicalize( sNurbsSurf) ; + if ( vU != nullptr) { + *vU = sNurbsSurf.vU ; + *vV = sNurbsSurf.vV ; + } + return NurbsToBezierSurface( sNurbsSurf) ; } else if ( const ON_PlaneSurface* onPlaneSurface = ON_PlaneSurface::Cast( onSurf)) { @@ -662,13 +679,42 @@ Import3dm::ConvertSurface( const ON_Surface* onSurf) ON_Interval onInter = onRevSurface->m_angle ; double dAngRotDeg = ( onInter[1] - onInter[0]) * RADTODEG ; double dAngStartDeg = onInter[0] * RADTODEG ; + + // uso la nurbs form per ottenere i vettori + ON_NurbsSurface onNurbsSurface ; + int nOk = onRevSurface->GetNurbForm( onNurbsSurface) ; + if ( nOk != 0) + return nullptr ; + ConvertSurface( &onNurbsSurface, vU, vV) ; + + // provo a convertire usando una bezier +#if SAVEREVOLVECURVE + vector vGeo ; + vGeo.push_back( pCurve->Clone()) ; + IGeoVector3d* pVec = CreateGeoVector3d() ; + pVec->Set( vtDir, ptTo) ; + vGeo.push_back( pCurve->Clone()) ; + vGeo.push_back( pVec) ; + SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\revolve_surf\\crv.nge") ; +#endif + + PtrOwner pSurfBez( GetSurfBezierByRevolve( pCurve, ptFrom, vtDir, false, 0.01)) ; + +#if SAVEREVOLVECURVE + if ( ! IsNull(pSurfBez)) + SaveGeoObj( pSurfBez->Clone(), "D:\\Temp\\bezier\\import3dm\\revolve_surf\\srf.nge") ; +#endif + if ( ! IsNull( pSurfBez) && pSurfBez->IsValid()) + return Release( pSurfBez) ; + + // sennò uso una trimesh PtrOwner pSurf( CreateSurfTriMesh()) ; if ( IsNull( pSurf)) return nullptr ; - // se l'angolo è significativo allora effettuo la rivoluzione + // se l'angolo è significativo allora effettuo la rivoluzione if ( dAngRotDeg > EPS_SMALL * 10) { pSurf.Set( GetSurfTriMeshByScrewing( pCurve, ptFrom, vtDir, dAngRotDeg, 0., false)) ; - // se la rivoluzione è meno di un angolo giro e la partenza non era a zero devo ruotare la superficie ottenuta + // se la rivoluzione è meno di un angolo giro e la partenza non era a zero devo ruotare la superficie ottenuta if ( dAngRotDeg < 360 - EPS_SMALL * 50 && onInter[0] * RADTODEG > EPS_SMALL * 50) pSurf->Rotate( ptFrom, vtDir, dAngStartDeg) ; } @@ -680,7 +726,7 @@ Import3dm::ConvertSurface( const ON_Surface* onSurf) int nOk = onSumSurface->GetNurbForm( onNurbsSurface) ; PtrOwner pSurf ; if ( nOk != 0) - pSurf.Set( ConvertSurface( &onNurbsSurface)) ; + pSurf.Set( ConvertSurface( &onNurbsSurface, vU, vV)) ; if ( ! IsNull( pSurf) && pSurf->IsValid()) return Release( pSurf) ; @@ -709,39 +755,50 @@ Import3dm::ConvertSurface( const ON_Surface* onSurf) PtrOwner pSurf ; // bool bTransposed = onSurfaceProxy->ProxySurfaceIsTransposed() ; if ( const ON_BrepFace* onBrepFace = ON_BrepFace::Cast( onSurfaceProxy)) { - // uso la nurbs form + // uso la nurbs form ON_NurbsSurface onNurbsSurface ; int nOk = onBrepFace->GetNurbForm( onNurbsSurface) ; if ( nOk != 0){ - pSurf.Set( ConvertSurface( & onNurbsSurface)) ; + pSurf.Set( ConvertSurface( & onNurbsSurface, vU, vV)) ; +#if SAVEREVOLVECURVE + SaveGeoObj( pSurf->Clone(), "D:\\Temp\\bezier\\import3dm\\revolve_surf\\srf_nurbs.nge") ; +#endif } else { - // QUI PERò NON TENGO CONTO DEL TRIM!!!!!! - // - // se non è riuscita la conversione in nurbs tengo la superficie originale + // QUI PERò NON TENGO CONTO DEL TRIM!!!!!! + // + // se non è riuscita la conversione in nurbs tengo la superficie originale const ON_Surface* onSurfFace = onBrepFace->ProxySurface() ; // qui devo applicare a mano le trasformazioni dalla superfice originale alla proxy // la funzione getNurbsForm lo fa in automatico - pSurf.Set( ConvertSurface( onSurfFace)) ; + pSurf.Set( ConvertSurface( onSurfFace, vU, vV)) ; LOG_ERROR( GetEE3Logger(), "Import3dm : Importing a surface without its trim, because of conversione errors") ; } + + ////// questa versione è da usare per usare le superfici proxy anziché la versione nurbs + //pSurf.Set( ConvertSurface( onBrepFace->ProxySurface(), vU, vV)) ; } else if ( const ON_OffsetSurface* onOffsetSurface = ON_OffsetSurface::Cast( onSurfaceProxy)) { //pSurf.Set( ConvertSurface( onOffsetSurface->BaseSurface())) ; ON_NurbsSurface onNurbsSurface ; int nOk = onOffsetSurface->GetNurbForm( onNurbsSurface) ; if ( nOk != 0) - pSurf.Set( ConvertSurface( &onNurbsSurface)) ; + pSurf.Set( ConvertSurface( &onNurbsSurface, vU, vV)) ; } else - pSurf.Set( ConvertSurface( onSurfaceProxy->ProxySurface())) ; + pSurf.Set( ConvertSurface( onSurfaceProxy->ProxySurface(), vU, vV)) ; return Release( pSurf) ; } return nullptr ; } +int nFailedBFace = 0, nFailedTm = 0, nFailedFr = 0, nFailedBz = 0, nFailedBTrim = 0 ; + +#if SAVETRIMLOOP +int nLoop = 0 ; +#endif //---------------------------------------------------------------------------- ISURFPOVECTOR @@ -755,17 +812,15 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) StmFromTriangleSoup stmSoup ; if ( ! stmSoup.Start()) return vSurf ; - bool bSurfTm = false ; - int nFailedBFace = 0, nFailedTm = 0, nFailedFr = 0, nFailedBz = 0, nFailedBTrim = 0 ; - int nFaceTot = onBrep->m_F.Count() ; for ( int i = 0 ; i < nFaceTot ; ++i) { - bool bOk = true ; ON_BrepFace* onFace = onBrep->Face( i) ; + bool bOk = true ; bool bRev = onFace->m_bRev ; const ON_Surface* onSurface = onFace->SurfaceOf() ; PtrOwner pSurf ; bool bTooSmallOnlyLoop = false ; + DBLVECTOR vU, vV ; if ( const ON_PlaneSurface* onPlaneSurface = ON_PlaneSurface::Cast( onSurface)) { SurfFlatRegionByContours SfrCntr ; // ricavo il riferimento del piano @@ -790,14 +845,14 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) } pSurf.Set( SfrCntr.GetSurf()) ; if ( ! IsNull( pSurf) && pSurf->IsValid()) { - // porto le coordinate dal riferimento del piano di trim alle coordinate globali + // porto le coordinate dal riferimento del piano di trim alle coordinate globali Frame3d frPlane ; frPlane.Set( ptOrig, vtX, vtY, vtZ) ; pSurf->ToGlob( frPlane) ; } } else - pSurf.Set( ConvertSurface( onFace)) ; + pSurf.Set( ConvertSurface( onFace, &vU, &vV)) ; if ( IsNull( pSurf) || ! pSurf->IsValid()) { // se la superficie aveva un solo loop e questo era troppo piccolo allora NON lo segno come errore @@ -806,10 +861,9 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) ++ nFailedBFace ; } else { - // se ho una trimesh o una flatregion la aggiungo alla zuppa, se è una bezier la aggiungo al vettore delle superfici + // se ho una trimesh o una flatregion la aggiungo alla zuppa, se è una bezier la aggiungo al vettore delle superfici int nType = pSurf->GetType() ; if ( nType == SRF_TRIMESH) { - bSurfTm = true ; PtrOwner pSurfTm( GetSurfTriMesh( Release( pSurf))) ; if ( !IsNull(pSurfTm) && pSurfTm->IsValid() ) { if ( bRev) @@ -820,7 +874,6 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) ++ nFailedTm ; } else if ( nType == SRF_FLATRGN) { - bSurfTm = true ; PtrOwner pSurfFr( GetSurfFlatRegion( Release( pSurf))) ; if ( ! IsNull( pSurfFr) && pSurfFr->IsValid()) { if ( bRev) @@ -833,13 +886,13 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) else if ( nType == SRF_BEZIER) { PtrOwner pSurfBezNew( GetSurfBezier( Release( pSurf))) ; if ( ! IsNull( pSurfBezNew) && pSurfBezNew->IsValid()) { - ON_BrepFace* onFace = onBrep->Face( i) ; SurfFlatRegionByContours SfrCntr ; const ON_Surface* onSurface = onFace->SurfaceOf() ; - // se la superficie era una superficie di rivoluzione, le eventuali curve di trim erano parametrizzate con la coordinata x in radianti, - // e non riferita allo spazio parametrico della nurbs corrispondente ( che sarebbe una nurbs razionale, dovendo approssimare un arco di circonferenza) - // devo quindi prelevare le curve di trim e cambiarne le coordinate per matcharle allo spazio parametrico della nurbs + // se la superficie era una superficie di rivoluzione, le eventuali curve di trim erano parametrizzate con la coordinata x in radianti, + // e non riferita allo spazio parametrico della nurbs corrispondente ( che sarebbe una nurbs razionale, dovendo approssimare un arco di circonferenza) + // devo quindi prelevare le curve di trim e cambiarne le coordinate per matcharle allo spazio parametrico della nurbs bool bAddedLoop = false ; + bool bTrimTooSmall = false ; if ( const ON_RevSurface* onRevSurf = ON_RevSurface::Cast( onSurface) ) { for ( int k = 0 ; k < onFace->LoopCount(); ++k ) { ICurve* pCrv( ConvertBrepLoop( onFace->Loop( k))) ; @@ -859,7 +912,7 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) bAddedLoop = true ; } else - continue ; + bTrimTooSmall = true ; } if ( ! bOk) continue ; @@ -867,7 +920,13 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) else { for ( int k = 0 ; k < onFace->LoopCount() && bOk ; ++k ) { PtrOwner pCrv( ConvertBrepLoop( onFace->Loop( k))) ; - if ( IsNull(pCrv) || ! pCrv->IsValid()) { + + #if SAVETRIMLOOP + SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\import3dm\\import_trim\\loop" + ToString(nLoop) + ".nge") ; + ++nLoop ; + #endif + + if ( IsNull( pCrv) || ! pCrv->IsValid()) { ++ nFailedBTrim ; bOk = false ; break ; @@ -880,19 +939,24 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) if ( SfrCntr.AddCurve( Release( pCrvCompo))) bAddedLoop = true ; } - else + else { + bTrimTooSmall = true ; continue ; + } } if ( ! bOk) continue ; } - if ( ! bAddedLoop) + if ( ! bAddedLoop) { + if ( ! bTrimTooSmall) + ++ nFailedBTrim ; continue ; + } ISurfFlatRegion* pSfrTrim = SfrCntr.GetSurf() ; - // questa regione di Trim deve essere riferita al rettangolo parametrico totale ( spaz param 1x1 -> regione trim 1000x1000) - // devo anche controllare che il sistema di riferimento dello spazio di trim totale sia giusto ( con l'angolo BottomLeft in (0,0) - //posizonato nel primo quadrante del piano XY) + // questa regione di Trim deve essere riferita al rettangolo parametrico totale ( spaz param 1x1 -> regione trim 1000x1000) + // devo anche controllare che il sistema di riferimento dello spazio di trim totale sia giusto ( con l'angolo BottomLeft in (0,0) + //posizonato nel primo quadrante del piano XY) double u0,u1,v0,v1 ; onFace->GetDomain(0, &u0, &u1) ; onFace->GetDomain(1, &v0, &v1) ; @@ -911,48 +975,70 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) bool bRat, bTrim ; pSurfBezNew->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrim) ; pSfrTrim->Scale( GLOB_FRM, nSpanU / dScaleU, nSpanV / dScaleV, 1.) ; - // se la superficie di partenza aveva vettori dei nodi non uniformi devo riscalare lo spazio parametrico in modo da renderli uniformi - // applicando così la trasformazione anche alle curve di trim. + // se la superficie di partenza aveva vettori dei nodi non uniformi devo riscalare lo spazio parametrico in modo da renderli uniformi + // applicando così la trasformazione anche alle curve di trim. ON_NurbsSurface onNurbsSurface ; onFace->GetNurbForm( onNurbsSurface) ; - // rendo uniforme lo spazio parametrico nella direzione dei parametri che non lo sono - // devo rendere lo spazio parametrico uniforme solo se la superficie è trimmata, sennò non serve - // per capire se la superficie sia trimmata controllo che lo spazio parametrico trimmato non coincida con tutto lo spazio parametrico + // rendo uniforme lo spazio parametrico nella direzione dei parametri che non lo sono + // devo rendere lo spazio parametrico uniforme solo se la superficie è trimmata, sennò non serve + // per capire se la superficie sia trimmata controllo che lo spazio parametrico trimmato non coincida con tutto lo spazio parametrico double dParamX = nSpanU * SBZ_TREG_COEFF ; double dParamY = nSpanV * SBZ_TREG_COEFF ; double dAreaTot = dParamX * dParamY ; double dAreaTrim = 0 ; pSfrTrim->GetArea( dAreaTrim) ; - if( dAreaTrim / dAreaTot < 1 - EPS_SMALL) { + if ( dAreaTrim / dAreaTot < 1 - EPS_SMALL) { bool bRescaled = false ; DBLVECTOR vU0 , vV0 ; - for ( int i = 0 ; i < onNurbsSurface.KnotCount( 0) ; ++i) - vU0.push_back( onNurbsSurface.Knot( 0, i) * nSpanU / dScaleU) ; - for ( int j = 0 ; j < onNurbsSurface.KnotCount( 1) ; ++j) - vV0.push_back( onNurbsSurface.Knot( 1, j) * nSpanV / dScaleV) ; - ISurfFlatRegion* pSfrTrimCopy( pSfrTrim->Clone()) ; + for ( int i = 0 ; i < ssize(vU) ; ++i) + vU0.push_back( vU[i] * nSpanU / dScaleU) ; + for ( int j = 0 ; j < ssize(vV) ; ++j) + vV0.push_back( vV[j] * nSpanV / dScaleV) ; dScaleU = dParamX ; dScaleV = dParamY ; - if ( ! MakeUniform( pSfrTrim, bRescaled, vU0, vV0, nDegU, nDegV, dScaleU, dScaleV, false)) { - // se make uniform fallisce potrei provare a farlo rigirare con gli offset ad ogni passaggio, per non avere errori nelle operazioni tra flat region///////// - //if ( *! MakeUniform( pSfrTrimCopy, bRescaled, vU0, vV0, nDegU, nDegV, dScaleU, dScaleV, true)) { - ++ nFailedBTrim ; - continue ; - //} - //else { - // delete pSfrTrim ; - // pSfrTrim = pSfrTrimCopy ; - // pSfrTrimCopy = nullptr ; - //} - } - //if ( bRescaled) { - // // per correggere eventuali crack create dal lavoro di collage sullo spazio parametrico faccio un OFFSET e controOFFSET - // pSfrTrim->Offset( 100*EPS_SMALL, ICurve::OFF_FILLET) ; - // pSfrTrim->Offset( -100*EPS_SMALL, ICurve::OFF_FILLET) ; + + //if ( ssize( vU0) == 0 || ssize(vV0) == 0 ) { + // vU0.clear() ; + // vV0.clear() ; + // int nU = onFace->SpanCount(0) ; + // int nV = onFace->SpanCount(1) ; + // double* vdU = new double[nU] ; + // double* vdV = new double[nV] ; + // onFace->GetSpanVector(0,vdU) ; + // onFace->GetSpanVector(1,vdV) ; + // for ( int i = 0 ; i < nU ; ++i) + // vU0.push_back( vdU[i] * nSpanU / dScaleU) ; + // for ( int j = 0 ; j < nV ; ++j) + // vV0.push_back( vdV[j] * nSpanU / dScaleU) ; + // delete[] vdU ; + // delete[] vdV ; + // ///////// PER FAR FUNZIONARE LA CANONICALIZE SERVONO ANCHE I PUNTI + // // devo solo togliere i nodi di troppo passando il vettore alla nurbsCanonicalize + // if ( onFace->IsPeriodic(0)) { + // CNurbsData cnU ; + // cnU.bPeriodic = true ; + // cnU.vU = vU0 ; + // NurbsCurveCanonicalize( cnU) ; + // vU0 = cnU.vU ; + // } + // if ( onFace->IsPeriodic(1)) { + // CNurbsData cnV ; + // cnV.bPeriodic = true ; + // cnV.vU = vV0 ; + // NurbsCurveCanonicalize( cnV) ; + // vV0 = cnV.vU ; + // } //} + + #if SAVEREVOLVETRIM + SaveGeoObj( pSfrTrim->Clone(), "D:\\Temp\\bezier\\import3dm\\trim_error\\non_uniform_trim.nge") ; + #endif + + if ( ! MakeUniform( pSfrTrim, bRescaled, vU0, vV0, nDegU, nDegV, dScaleU, dScaleV, false)) { + ++ nFailedBTrim ; + continue ; + } pSurfBezNew->SetTrimRegion( *pSfrTrim) ; - if ( pSfrTrimCopy != nullptr) - delete pSfrTrimCopy ; } else pSfrTrim->Scale( GLOB_FRM, nSpanU / dScaleU, nSpanV / dScaleV, 1) ; @@ -965,10 +1051,14 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) pSurfBezNew->RemoveCollapsedSpans() ; +#if SAVEREVOLVESURF + SaveGeoObj( pSurfBezNew->Clone(), "D:\\Temp\\bezier\\import3dm\\revolve_surf\\surf_ok.nge") ; +#endif + if ( ! bForceTriMesh) vSurf.emplace_back( Release( pSurfBezNew)) ; else - stmSoup.AddSurfTriMesh( *(Release( pSurfBezNew)->GetAuxSurf())) ; + stmSoup.AddSurfTriMesh( *(pSurfBezNew->GetAuxSurf())) ; } else { ++nFailedBz ; @@ -1000,8 +1090,10 @@ Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh) if ( ! stmSoup.End()) return vSurf ; - if ( bSurfTm || bForceTriMesh) - vSurf.emplace_back( stmSoup.GetSurf()) ; + + PtrOwner pSTM( stmSoup.GetSurf()) ; + if ( ! IsNull( pSTM) && pSTM->IsValid()) + vSurf.emplace_back( Release( pSTM)) ; return vSurf ; } diff --git a/Import3dm.h b/Import3dm.h index aa358ee..8768ce6 100644 --- a/Import3dm.h +++ b/Import3dm.h @@ -47,7 +47,7 @@ class Import3dm : public IImport3dm Vector3d ConvertVector( const ON_2dVector& onVector) { return Vector3d( onVector.x, onVector.y, 0) ; } ; ICurve* ConvertCurve( const ON_Curve* onCurve) ; - ISurf* ConvertSurface( const ON_Surface* onSurf) ; + ISurf* ConvertSurface( const ON_Surface* onSurf, DBLVECTOR* vU = nullptr, DBLVECTOR* vV = nullptr) ; ISURFPOVECTOR ConvertExtrusion( const ON_Extrusion* onExtrusion) ; ISurfTriMesh* ConvertMesh( const ON_Mesh* onMesh) ; std::vector> ConvertAnnotation( const ON_Annotation* onAnnot, const ON_DimStyle* onDimStyle, double dTextHeight, double dExtLine, double dArrLen, double dTextDist,