//---------------------------------------------------------------------------- // EgalTech 2025-2025 //---------------------------------------------------------------------------- // File : EXE_Trimming.cpp Data : 25.10.25 Versione : 2.7j3 // Funzioni per le lavorazioni di Trimming. // // Modifiche : 23.10.25 RE Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "EXE.h" #include "EXE_Macro.h" #include "DllExchange.h" #include "GeoTools.h" #include "AuxTools.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EXeExecutor.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EGkSurfLocal.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkTrimming.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include #include using namespace std ; static string s_sKey_Sync_Coord = "KeyOldCoord" ; static string s_sKey_Auto_Trim = "AutoTrim" ; // --------------------------------------------------------------------------- bool ExeTrimmingAutoSearch( int nParentId, int nSurfLayerId, double dShapeLinTol, double dShapeAngTol, double dLinTol, double dEdgeLinTol, double dAngTol, double dAngFaceTol, const STRVECTOR& vsShapes) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Se non ho geometrie da ricercare, non faccio nulla if ( vsShapes.empty()) return true ; // Recupero le superfici presenti nel Layer CISURFPVECTOR vSurfs ; vSurfs.reserve( pGeomDB->GetGroupObjs( nSurfLayerId)) ; int nId = pGeomDB->GetFirstInGroup( nSurfLayerId) ; while ( nId != GDB_ID_NULL) { // Recupero l'entità const IGeoObj* pGeoObj = pGeomDB->GetGeoObj( nId) ; if ( pGeoObj != nullptr) { // Recupero il Tipo int nType = pGeoObj->GetType() ; if ( nType == SRF_TRIMESH || nType == SRF_BEZIER) { // Recupero la superficie const ISurf* pSurf = GetSurf( pGeoObj) ; if ( pSurf != nullptr && pSurf->IsValid()) vSurfs.emplace_back( pSurf) ; } } nId = pGeomDB->GetNext( nId) ; } // Se non ho superfici non faccio nulla if ( vSurfs.empty()) return false ; // Recupero Le Superfici Selezionate, Le Curve e Le Bezier rigate ISURFPOMATRIX matSelSurfMatrix ; ICRVCOMPOPOMATRIX matCompoBorders ; ISURFBEZPOVECTOR vSurfBz ; bool bOk = GetTrimmingAutoEntities( vSurfs, dShapeLinTol, dShapeAngTol, dLinTol, dEdgeLinTol, dAngTol, dAngFaceTol, vsShapes, matSelSurfMatrix, matCompoBorders, vSurfBz) ; // Per sicurezza verifico che tutte le entità siano a dimensione corretta bOk = bOk && ( ssize( matSelSurfMatrix) == ssize( matCompoBorders)) && ( ssize( matSelSurfMatrix) == ssize( vSurfBz)) ; // Per ogni Entità ricavata inserisco le Geometrie nel Layer // NB. Ordine di Inserimento : Surf -> Edges -> bezier // Una anomalia nella serie blocca il flusso corrente e passa al successivo int nCount = -1 ; for ( int i = 0 ; bOk && i < int( matSelSurfMatrix.size()) ; ++ i) { // Verifico che la Superficie sia Valida bool bOkEntity = true ; for ( int j = 0 ; bOkEntity && j < ssize( matSelSurfMatrix[i]) ; ++ j) bOkEntity = ( ! IsNull( matSelSurfMatrix[i][j]) && matSelSurfMatrix[i][j]->IsValid()) ; if ( ! bOkEntity) continue ; // anomalia serie livello superfici di selezione for ( int j = 0 ; bOk && j < ssize( matSelSurfMatrix[i]) ; ++ j) { int nSurfId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( matSelSurfMatrix[i][j])) ; bOk = ( ( nSurfId != GDB_ID_NULL) && ( pGeomDB->SetInfo( nSurfId, s_sKey_Auto_Trim, ToString( ++ nCount)))) ; } if ( ! bOk) break ; // anomalia bloccante // Verifico che Le Curve di Edges ( Bezier ) siano Valide for ( int j = 0 ; bOkEntity && j < ssize( matCompoBorders[i]) ; ++ j) bOkEntity = ( ! IsNull( matCompoBorders[i][j]) && matCompoBorders[i][j]->IsValid()) ; if ( ! bOkEntity) continue ; // anomalia serie livello curve di bordo for ( int j = 0 ; bOk && j < ssize( matCompoBorders[i]) ; ++ j) { int nCrvId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( matCompoBorders[i][j])) ; bOk = ( ( nCrvId != GDB_ID_NULL) && ( pGeomDB->SetInfo( nCrvId, s_sKey_Auto_Trim, ToString( nCount)))) ; } if ( ! bOk) break ; // anomalia bloccante // Verifico che le Superfici di Bezier rigate siano Valide bOkEntity = ( ! IsNull( vSurfBz[i]) && vSurfBz[i]->IsValid()) ; if ( ! bOkEntity) continue ; // anomalia seria livello Bezier Rigata int nBzId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vSurfBz[i])) ; bOk = ( ( nBzId != GDB_ID_NULL) && ( pGeomDB->SetInfo( nBzId, s_sKey_Auto_Trim, ToString( nCount)))) ; if ( ! bOk) break ; // anomali bloccante } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingAutoSearch(" + ToString( nParentId) + "," + ToString( nSurfLayerId) + "," + ToString( dShapeLinTol) + "," + ToString( dShapeAngTol) + "," + ToString( dLinTol) + "," + ToString( dEdgeLinTol) + "," + ToString( dAngTol) + "," + ToString( dAngFaceTol) + "," + ToString( vsShapes) + ")" + " -- bOk=" + ToString( bOk) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetSurfTmFaceAdj( int nSurfId, const INTVECTOR& vTria, const PNTVECTOR& vPts, double dAngTol, double dSize, double dSizeTol, INTVECTOR& vOtherFaces) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Recupero la superficie TriMesh const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nSurfId)) ; bool bOk = ( pStm != nullptr && pStm->IsValid()) ; // Verifico che le facce appartengano alla superficie bOk = bOk && ( ! vTria.empty()) ; // Recupero l'insieme dei triangoli if ( bOk) { INTVECTOR vOtherTria ; vOtherTria.reserve( pStm->GetTriangleCount()) ; bOk = GetTrimmingStmAdjTria( pStm, vTria, vPts, dAngTol, dSize, dSizeTol, vOtherTria) ; // Per ogni triangolo ricavato, recupero la faccia corrispondente set setFaces ; for ( const int& nT : vOtherTria) setFaces.insert( pStm->GetFacetFromTria( nT)) ; vOtherFaces.assign( setFaces.begin(), setFaces.end()) ; } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetSurfTmFromFaceAdj(" + ToString( nSurfId) + "," + ToString( vTria) + "," + ToString( dAngTol) + ")" + " -- bOk=" + ToString( bOk) + "vOtherFaces=" + ToString( vOtherFaces) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- int ExeTrimmingGetSurfTmFromStmFaces( int nParentId, int nSurfId, const INTVECTOR& vFaces) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) // Recupero il riferimento del gruppo di destinazione Frame3d frDest ; if ( ! pGeomDB->GetGlobFrame( nParentId, frDest)) return GDB_ID_NULL ; // Recupero la superficie TriMesh const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nSurfId)) ; if ( pStm == nullptr || ! pStm->IsValid()) return GDB_ID_NULL ; // Verifico che le facce appartengano alla superficie if ( vFaces.empty()) return CMD_ID_NULL ; for ( int nF = 0 ; nF < int( vFaces.size()) ; ++ nF) { double dArea = 0. ; if ( ! pStm->GetFacetArea( vFaces[nF], dArea)) return GDB_ID_NULL ; } // Definisco la superficie StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ; for ( int nF = 0 ; nF < int( vFaces.size()) ; ++ nF) { INTVECTOR vT ; if ( ! pStm->GetAllTriaInFacet( vFaces[nF], vT)) return GDB_ID_NULL ; for ( int nT = 0 ; nT < int( vT.size()) ; ++ nT) { Triangle3d Tria ; if ( ! pStm->GetTriangle( vT[nT], Tria) || ! TriaSoup.AddTriangle( Tria)) return GDB_ID_NULL ; } } TriaSoup.End() ; PtrOwner pStmTria( TriaSoup.GetSurf()) ; if ( IsNull( pStmTria) || ! pStmTria->IsValid() || pStmTria->GetTriangleCount() == 0) return GDB_ID_NULL ; // Aggiungo la superficie al DB int nNewSurfId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pStmTria)) ; ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "TrimmingGetSurfTmFromStmFaces(" + ToString( nParentId) + "," + ToString( nSurfId) + "," + ToString( vFaces) + ")" + " -- nId=" + ToString( nNewSurfId) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return nNewSurfId ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetAdjSurfs( const INTVECTOR& vSurfId, const INTVECTOR& vOtherSurfId, double dLinTol, double dAngTol, double dAngFaceTol, INTVECTOR& vResId) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Recupero le superfici di Riferimento CISURFPVECTOR vRefSurf ; vRefSurf.reserve( vSurfId.size()) ; bool bOk = true ; for ( int i = 0 ; bOk && i < int( vSurfId.size()) ; ++ i) { const ISurf* pSurf = GetSurf( pGeomDB->GetGeoObj( vSurfId[i])) ; bOk = ( pSurf != nullptr && pSurf->IsValid()) ; vRefSurf.emplace_back( pSurf) ; } // Recupero le superfici complessive, escludendo eventualmente quelle di riferimento se presenti CISURFPVECTOR vOtherSurf ; vOtherSurf.reserve( vOtherSurfId.size()) ; INTVECTOR vIds ; for ( int i = 0 ; bOk && i < int( vOtherSurfId.size()) ; ++ i) { if ( find( vSurfId.begin(), vSurfId.end(), vOtherSurfId[i]) == vSurfId.end()) { const ISurf* pSurf = GetSurf( pGeomDB->GetGeoObj( vOtherSurfId[i])) ; bOk = ( pSurf != nullptr && pSurf->IsValid()) ; vOtherSurf.emplace_back( pSurf) ; vIds.push_back( vOtherSurfId[i]) ; } } // Recupero le facce adiancenti nella tolleranza richiesta INTVECTOR vMyInds ; bOk = bOk && GetTrimmingAdjSurfs( vRefSurf, vOtherSurf, dLinTol, dAngTol, dAngFaceTol, vMyInds) ; if ( bOk) { for ( const int& myInd : vMyInds) vResId.push_back( vIds[myInd]) ; } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetAdjSurfs(" + ToString( vSurfId) + "," + ToString( vOtherSurfId) + "," + ToString( dAngTol) + ")" + " -- bOk=" + ToString( bOk) + ",vResId=" + ToString( vResId) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetBorders( int nParentId, const SELVECTOR& vIds, double dLinTol, double dAngTol, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Parametri da restituire nFirstId = GDB_ID_NULL ; nCount = 0 ; // vIds : vettore di { nId = SurfId, nSubId = nSurfFace } // Controllo che vIds non sia vuoto bool bOk = ( ! vIds.empty()) ; // Recupero il riferimento della prima superficie Frame3d frSurf ; bOk = bOk && pGeomDB->GetGlobFrame( vIds[0].nId, frSurf) ; // Recupero il riferimento dei gruppi di destinazione Frame3d frDest ; bOk = bOk && pGeomDB->GetGlobFrame( nParentId, frDest) ; // Recupero gli Id univoci delle superfici selezionate INTSET setUniqueId ; for ( const SelData& nIds : vIds) setUniqueId.insert( nIds.nId) ; // Recupero le superfici e le porto tutte in locale alla prima unordered_map uMapPos ; uMapPos.reserve( setUniqueId.size()) ; SURFLOCALVECTOR vSurfL ; vSurfL.reserve( setUniqueId.size()) ; CISURFPVECTOR vpSurf ; vpSurf.reserve( setUniqueId.size()) ; int nSurf = 0 ; for ( auto nIter = setUniqueId.begin() ; bOk && nIter != setUniqueId.end() ; ++ nIter) { vSurfL.emplace_back( pGeomDB, *nIter, frSurf) ; bOk = ( vSurfL.back().Get() != nullptr) ; vpSurf.emplace_back( vSurfL.back().Get()) ; uMapPos[*nIter] = nSurf ; ++ nSurf ; } // Recupero il vettore di Selezione associato non più agli Id delle superficie ma alle loro posizioni nel vettore SELVECTOR vFaces ; vFaces.reserve( vIds.size()) ; for ( int i = 0 ; bOk && i < int( vIds.size()) ; ++ i) vFaces.emplace_back( uMapPos[vIds[i].nId], vIds[i].nSub) ; // Calcolo le curve di Edge grezze ( quindi i tratti lineari) ICRVCOMPOPOVECTOR vRawEdges ; bOk = bOk && GetTrimmingRawEdges( vpSurf, vFaces, dLinTol, dAngTol, vRawEdges) && ( ! vRawEdges.empty()) ; // Calcolo le curve di Edge approssimate mediante curve di Bezier ICRVCOMPOPOVECTOR vBezierEdges ; bOk = bOk && GetTrimmingBezierEdges( vRawEdges, dLinTol, dAngTol, vBezierEdges) ; nCount = int( vBezierEdges.size()) ; if ( bOk) { // Scorro i gli Edges ottenuti for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) { vBezierEdges[nCrv]->ToLoc( frDest) ; // Inserisco la curva nel DB Geometrico int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nCrv])) ; bOk = ( nCurrId != GDB_ID_NULL) ; if ( nCrv == 0) nFirstId = nCurrId ; } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetBorders(" + IdToString( nParentId) + "," + ToString( dLinTol) + "," + ToString( dAngTol) + ")" ; sLua += " -- bOk=" + ToString( bOk) + " -- FirstId=" + ToString( nFirstId) + " CurveCount=" + ToString( nCount) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetBordersByNormals( int nParentId, const SELVECTOR& vIds, double dLinTol, double dAngTol, double dThick, Point3d& ptNear, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Parametri da restituire nFirstId = GDB_ID_NULL ; nCount = 0 ; // vIds : vettore di { nId = SurfId, nSubId = nSurfFace } // Controllo che vIds non sia vuoto bool bOk = ( ! vIds.empty()) ; // Recupero il riferimento della prima superficie Frame3d frSurf ; bOk = bOk && pGeomDB->GetGlobFrame( vIds[0].nId, frSurf) ; // Recupero il riferimento dei gruppi di destinazione Frame3d frDest ; bOk = bOk && pGeomDB->GetGlobFrame( nParentId, frDest) ; // Recupero gli Id univoci delle superfici selezionate INTSET setUniqueId ; for ( const SelData& nIds : vIds) setUniqueId.insert( nIds.nId) ; // Recupero le superfici e le porto tutte in locale alla prima unordered_map uMapPos ; uMapPos.reserve( setUniqueId.size()) ; SURFLOCALVECTOR vSurfL ; vSurfL.reserve( setUniqueId.size()) ; CISURFPVECTOR vpSurf ; vpSurf.reserve( setUniqueId.size()) ; int nSurf = 0 ; for ( auto nIter = setUniqueId.begin() ; bOk && nIter != setUniqueId.end() ; ++ nIter) { vSurfL.emplace_back( pGeomDB, *nIter, frSurf) ; bOk = ( vSurfL.back().Get() != nullptr) ; vpSurf.emplace_back( vSurfL.back().Get()) ; uMapPos[*nIter] = nSurf ; ++ nSurf ; } // Recupero il vettore di Selezione associato non più agli Id delle superficie ma alle loro posizioni nel vettore SELVECTOR vFaces ; vFaces.reserve( vIds.size()) ; for ( int i = 0 ; bOk && i < int( vIds.size()) ; ++ i) vFaces.emplace_back( uMapPos[vIds[i].nId], vIds[i].nSub) ; // Calcolo le curve di Edge approssimate mediante curve di Bezier ICRVCOMPOPOVECTOR vBezierEdges ; bOk = bOk && GetTrimmingFinalBorders( vpSurf, vFaces, dLinTol, dAngTol, dThick, vBezierEdges) ; if ( bOk) { // Se non ho un punto di vicinanza, le inserisco tutte if ( ! ptNear.IsValid()) { nCount = int( vBezierEdges.size()) ; // Scorro i gli Edges ottenuti for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) { vBezierEdges[nCrv]->ToLoc( frDest) ; // Inserisco la curva nel DB Geometrico int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nCrv])) ; bOk = ( nCurrId != GDB_ID_NULL) ; if ( nCrv == 0) nFirstId = nCurrId ; } } // Se ho un punto di vicinanza, cerco la coppia di curve più vicina else { // Se solo una coppia di curve, le inserisco e non ho ambiguità if ( int( vBezierEdges.size()) == 2) { nCount = int( vBezierEdges.size()) ; // Scorro gli Edges ottenuti for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) { vBezierEdges[nCrv]->ToLoc( frDest) ; // Inserisco la curva nel DB Geometrico int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nCrv])) ; bOk = ( nCurrId != GDB_ID_NULL) ; if ( nCrv == 0) nFirstId = nCurrId ; } } // altrimenti cerco la coppia più vicia else { double dSqMinDist = INFINITO ; int nInd = 0 ; for ( int i = 0 ; i + 1 < int( vBezierEdges.size()) ; i = i + 2) { double dSqDist = 0., dSqDist1 = 0. ; if ( DistPointCurve( ptNear, *vBezierEdges[i]).GetSqDist( dSqDist) && DistPointCurve( ptNear, *vBezierEdges[i + 1]).GetSqDist( dSqDist1)) { double dCurrMinSqDist = min( dSqDist, dSqDist1) ; if ( dCurrMinSqDist < dSqMinDist) { dSqMinDist = dCurrMinSqDist ; nInd = i ; } } } vBezierEdges[nInd]->ToLoc( frDest) ; vBezierEdges[nInd + 1]->ToLoc( frDest) ; int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nInd])) ; int nCurrId1 = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nInd + 1])) ; bOk = ( nCurrId != GDB_ID_NULL && nCurrId1 != GDB_ID_NULL) ; if ( bOk) { nFirstId = nCurrId1 ; nCount = 2 ; } } } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetBordersByNormals(" + IdToString( nParentId) + "," + ToString( dLinTol) + "," + ToString( dAngTol) + ")" ; sLua += " -- bOk=" + ToString( bOk) + " -- FirstId=" + ToString( nFirstId) + " CurveCount=" + ToString( nCount) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetFinalBorders( int nParentId, const INTVECTOR& vCrvBezierId, double dLinTol, double dAngTol, const PNTVECTOR& vBrkPts, double dThick, double dThickTol, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Parametri da restituire nFirstId = GDB_ID_NULL ; nCount = 0 ; // Recupero il riferimento del gruppo di destinazione Frame3d frDest ; bool bOk = ( pGeomDB->GetGlobFrame( nParentId, frDest)) ; // Recupero le curve di Bordo approssimate come Bezier ICRVCOMPOPOVECTOR vCompoBezierEdges ; vCompoBezierEdges.reserve( vCrvBezierId.size()) ; for ( int nCrv = 0 ; bOk && nCrv < int( vCrvBezierId.size()) ; ++ nCrv) { const ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vCrvBezierId[nCrv])) ; bOk = ( pCrv != nullptr && pCrv->IsValid()) ; if ( bOk) { PtrOwner pCompoRawEdges( ConvertCurveToComposite( pCrv->Clone())) ; bOk = ( ! IsNull( pCompoRawEdges) && pCompoRawEdges->IsValid() && vCompoBezierEdges.emplace_back( Release( pCompoRawEdges))) ; } } // Converto i punti in coppie di punti ( se dispari l'ultimo viene ignorato) BIPNTVECTOR vBreakingPts ; vBreakingPts.reserve( int( int( vBrkPts.size()) / 2)) ; for ( int nPt = 0 ; bOk && nPt < int( vBrkPts.size()) - 1 ; nPt += 2) vBreakingPts.emplace_back( make_pair( vBrkPts[nPt], vBrkPts[nPt+1])) ; if ( int( vBrkPts.size()) % 2 != 0) LOG_INFO( GetCmdLogger(), "Warning in EgtExtractSurfFrChunkLoops : Odd number of breaking points") ; // Calcolo le curve di Edge bOk = bOk && GetTrimmingFinalBorders( vCompoBezierEdges, dLinTol, dAngTol, vBreakingPts, dThick, dThickTol) ; nCount = int( vCompoBezierEdges.size()) ; if ( bOk) { // Scorro i gli Edges ottenuti for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) { vCompoBezierEdges[nCrv]->ToLoc( frDest) ; // Inserisco la curva nel DB Geometrico int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vCompoBezierEdges[nCrv])) ; bOk = ( nCurrId != GDB_ID_NULL) ; if ( nCrv == 0) nFirstId = nCurrId ; } ExeSetModified() ; } // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetFinalBorders(" + IdToString( nParentId) + "," + ToString( vCrvBezierId) + "," + ToString( dLinTol) + "," + ToString( dAngTol) + "," ; sLua += "{" ; for ( int nP = 0 ; nP < int( vBrkPts.size()) ; ++ nP) { sLua += "(" + ToString( vBrkPts[nP].x) + ", " + ToString( vBrkPts[nP].y) + ", " + ToString( vBrkPts[nP].z) + ")" + ( nP != int( vBrkPts.size()) - 1 ? "," : "") ; } sLua += "}" ; sLua += ToString( dThick) + "," + ToString( dThickTol) + ")" ; sLua += " -- bOk=" + ToString( bOk) + " -- FirstId=" + ToString( nFirstId) + " CurveCount=" + ToString( nCount) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- int ExeTrimmingGetRuledBezier( int nParentId, const INTVECTOR& vIds, int nEdge1Id, int nEdge2Id, double dLinTol, const INTVECTOR& vnLineId) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) // Aggiusto la tolleranza lineare se necessario double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; // Recupero il riferimento dei gruppi di destinazione Frame3d frDest ; bool bOk = pGeomDB->GetGlobFrame( nParentId, frDest) ; // Recupero la prima curva const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nEdge1Id)) ; bOk = bOk && ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid()) ; // Recupero la seconda curva const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nEdge2Id)) ; bOk = bOk && ( pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ; // Se ci sono delle superfici di riferimento CISURFPVECTOR vpSurf ; vpSurf.reserve( vIds.size()) ; if ( ! vIds.empty()) { SURFLOCALVECTOR vSurfL ; vSurfL.reserve( vIds.size()) ; // Recupero il riferimento della prima superficie Frame3d frSurf ; bOk = bOk && ( pGeomDB->GetGlobFrame( vIds[0], frSurf)) ; // Porto le altre nel riferimento della prima for ( int nSurf = 0 ; bOk && nSurf < int( vIds.size()) ; ++ nSurf) { vSurfL.emplace_back( pGeomDB, vIds[nSurf], frSurf) ; if ( vSurfL.back().Get() == nullptr) { bOk = false ; break ; } vpSurf.emplace_back( vSurfL.back().Get()) ; } } // Recupero i punti di sincronizzazione ( se presenti) BIPNTVECTOR vSyncPoints ; vSyncPoints.reserve( pGeomDB->GetGroupObjs( vnLineId.size())) ; INTVECTOR vIndPriority ; vIndPriority.reserve( vSyncPoints.size()) ; INTVECTOR vIndVisible ; vIndVisible.reserve( vSyncPoints.size()) ; for ( int i = 0 ; bOk && i < int( vnLineId.size()) ; ++ i) { // Recupero la Curva const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( vnLineId[i])) ; bOk = bOk && ( pLine != nullptr && pLine->IsValid()) ; if ( bOk) { Point3d ptStart ; pLine->GetStartPoint( ptStart) ; Point3d ptEnd ; pLine->GetEndPoint( ptEnd) ; vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; // Verifico se la linea è visibile all'utente int nStatus = GDB_ST_OFF ; if ( pGeomDB->GetStatus( vnLineId[i], nStatus) && nStatus == GDB_ST_ON) vIndVisible.emplace_back( int( vSyncPoints.size() - 1)) ; // Verifico mediante le Info se la curva è stata modificata o aggiunta ( quindi prioritaria) DBLVECTOR vdOldCoor ; vdOldCoor.reserve( 6) ; if ( ! pGeomDB->GetInfo( vnLineId[i], s_sKey_Sync_Coord, vdOldCoor) || int( vdOldCoor.size()) != 6 || ! AreSamePointApprox( ptStart, Point3d( vdOldCoor[0], vdOldCoor[1], vdOldCoor[2])) || ! AreSamePointApprox( ptEnd, Point3d( vdOldCoor[3], vdOldCoor[4], vdOldCoor[5]))) vIndPriority.emplace_back( int( vSyncPoints.size()) - 1) ; } } // Recupero la superficie Bezier rigata PtrOwner pSurfBzRuled ; if ( bOk) { pSurfBzRuled.Set( GetTrimmingRuledBezier( vpSurf, pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints, vIndPriority, vIndVisible)) ; bOk = bOk && ( ! IsNull( pSurfBzRuled) && pSurfBzRuled->IsValid()) ; } // Inserisco la curva nel DB Geometrico int nSurfBzId = GDB_ID_NULL ; if ( bOk) { pSurfBzRuled->ToLoc( frDest) ; nSurfBzId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pSurfBzRuled)) ; bOk = bOk && ( nSurfBzId != GDB_ID_NULL) ; } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetRuledBezier(" + ToString( nParentId) + "," + ToString( vIds) + "," + ToString( nEdge1Id) + "," + ToString( nEdge2Id) + "," + ToString( dLinTol) + ")" + " -- bOk=" + ToString( bOk) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } // Restituisco il risultato return nSurfBzId ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetSurfBzSyncPoints( int nParentId, int nEdge1Id, int nEdge2Id, double dLinTol, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Se necessario aggiusto le tolleranze double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; // Recupero il riferimento del gruppo di destinazione Frame3d frDest ; bool bOk = ( pGeomDB->GetGlobFrame( nParentId, frDest)) ; // Recupero le due Curve di bordo const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nEdge1Id)) ; const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nEdge2Id)) ; bOk = bOk && ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid() && pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ; // Recupero i punti di sincronizzazione BIPNTVECTOR vSyncPoints ; bOk = bOk && GetTrimmingSurfBzSyncPoints( pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints) && ( ! vSyncPoints.empty()) ; nCount = int( vSyncPoints.size()) ; // Inserisco i tratti di sincronizzazione nel DB Geometrico for ( int nL = 0 ; nL < int( vSyncPoints.size()) ; ++ nL) { PtrOwner pLine( CreateCurveLine()) ; if ( ! IsNull( pLine) && pLine->Set( vSyncPoints[nL].first, vSyncPoints[nL].second)) { int nLineId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ; if ( nLineId != GDB_ID_NULL) { if ( nL == 0) nFirstId = nLineId ; // Memorizzo come Info le coordinate dei punti ( per tenere traccia in futuro di modifiche) DBLVECTOR vdCoordInfo = { vSyncPoints[nL].first.x, vSyncPoints[nL].first.y, vSyncPoints[nL].first.z, vSyncPoints[nL].second.x, vSyncPoints[nL].second.y, vSyncPoints[nL].second.z} ; pGeomDB->SetInfo( nLineId, s_sKey_Sync_Coord, vdCoordInfo) ; } } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetSurfBzSyncPoints(" + ToString( nParentId) + "," + ToString( nEdge1Id) + "," + ToString( nEdge2Id) + "," + ToString( dLinTol) + "," + ToString( nFirstId) + "," + ToString( nCount) + ")" + " -- bOk=" + ToString( bOk) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } //---------------------------------------------------------------------------- bool ExeTrimmingSkimSyncPoints( int nEdge1Id, int nEdge2Id, const INTVECTOR& vnLineId, double dLinTol, double dAngTol, int nMaxInvLine) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Se necessario aggiusto le tolleranze double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; double dMyAngTol = Clamp( dAngTol, 1., 45.) ; int nMyMaxInvLine = Clamp( nMaxInvLine, 1, 100) ; // Recupero le due Curve di bordo const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nEdge1Id)) ; const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nEdge2Id)) ; bool bOk = ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid() && pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ; // Definisco il vettore degli Estremi BIPNTVECTOR vSyncPoints ; vSyncPoints.reserve( vnLineId.size()) ; for ( int i = 0 ; bOk && i < int( vnLineId.size()) ; ++ i) { const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( vnLineId[i])) ; bOk = ( pLine != nullptr && pLine->IsValid()) ; if ( bOk) { Point3d ptStart, ptEnd ; bOk = ( pLine->GetStartPoint( ptStart) && pLine->GetEndPoint( ptEnd)) ; if ( bOk) vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; } } // Scelta di Selezione delle linee di sincronizzazione // 1) In presenza di Spigoli, vengono sempre visualizzate ( Spigolo definito da tolleranza angolare) // 2) 1 Curva su 'nMyMaxInvLine' viene mostrata altrimenti int nInvisibleCount = 0 ; for ( int nL = 0 ; bOk && nL < int( vSyncPoints.size()) ; ++ nL) { bool bVisible = false ; Point3d ptUseless = P_INVALID ; // Recupero gli Estremi e controllo se sono su uno spigolo tra una delle due curve double dUS = 0. ; bOk = bOk && pCrvEdge1->GetParamAtPoint( vSyncPoints[nL].first, dUS, dMyLinTol) ; if ( bOk) { Vector3d vtPrev, vtAft ; bOk = pCrvEdge1->GetPointD1D2( dUS, ICurve::FROM_MINUS, ptUseless, &vtPrev) && pCrvEdge1->GetPointD1D2( dUS, ICurve::FROM_PLUS, ptUseless, &vtAft) ; if ( bOk) { vtPrev.Normalize() ; vtAft.Normalize() ; bVisible = ( vtPrev * vtAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) ; if ( ! bVisible) { double dUE = 0. ; bOk = bOk && pCrvEdge2->GetParamAtPoint( vSyncPoints[nL].second, dUE, dMyLinTol) ; bOk = pCrvEdge2->GetPointD1D2( dUE, ICurve::FROM_MINUS, ptUseless, &vtPrev) && pCrvEdge2->GetPointD1D2( dUE, ICurve::FROM_PLUS, ptUseless, &vtAft) ; if ( bOk) { vtPrev.Normalize() ; vtAft.Normalize() ; bVisible = ( vtPrev * vtAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) ; } } } if ( bOk) { // Imposto lo Stato if ( ! bVisible) ++ nInvisibleCount ; if ( nInvisibleCount == nMyMaxInvLine) { bVisible = true ; nInvisibleCount = 0 ; } pGeomDB->SetStatus( vnLineId[nL], bVisible ? GDB_ST_ON : GDB_ST_OFF) ; } } } // Se richiesto, salvo il comando Lua equivalente // ????????????? return bOk ; }