//---------------------------------------------------------------------------- // 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/EGkGeoVector3d.h" #include "/EgtDev/Include/EGkCurveAux.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 "/EgtDev/Include/EGkDistPointSurfBz.h" #include "/EgtDev/Include/EGkSbzFromCurves.h" #include #include using namespace std ; // --------------------------------------------------------------------------- bool ExeTrimmingGetHoleBorder( int nParentId, const INTVECTOR& vSurfIds, const INTVECTOR& vOtherSurfIds, double dSurfLinTol, double dSurfAngTol, double dEdgeLinTol, double dEdgeAngTol, double dEdgeThick, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Inizializzo i valori di ritorno nFirstId = GDB_ID_NULL ; nCount = 0 ; // Se non ho geometrie da ricercare, non faccio nulla if ( vSurfIds.empty()) return true ; // Recupero le superfici da cui estrarre i bordi CISURFPVECTOR vpSurfs ; vpSurfs.reserve( vSurfIds.size()) ; for ( int i = 0 ; i < ssize( vSurfIds) ; ++ i) { int nSurfId = vSurfIds[i] ; // Recupero l'entità const IGeoObj* pGeoObj = pGeomDB->GetGeoObj( nSurfId) ; 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()) vpSurfs.emplace_back( pSurf) ; } } } // Se non ho superfici non faccio nulla if ( vpSurfs.empty()) return false ; // Calcolo il Centroide delle superfici complessive Point3d ptRef = P_INVALID ; if ( ! vOtherSurfIds.empty()) { int nToTSurf = 0 ; for ( int nOtherSurfId : vOtherSurfIds) { // Recupero l'entità const IGeoObj* pGeoObj = pGeomDB->GetGeoObj( nOtherSurfId) ; 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()) { // Recupero il Centroide Point3d ptCentroid ; pSurf->GetCentroid( ptCentroid) ; if ( ! ptRef.IsValid()) ptRef = ptCentroid ; else ptRef += ptCentroid ; ++ nToTSurf ; } } } } if ( nToTSurf > 0) { for ( const ISurf* pSurf : vpSurfs) { Point3d ptCentroid ; pSurf->GetCentroid( ptCentroid) ; if ( ! ptRef.IsValid()) ptRef = ptCentroid ; else ptRef += ptCentroid ; ++ nToTSurf ; } ptRef /= nToTSurf ; } } // Recupero i Bordi per fori ed asole ICRVCOMPOPOVECTOR vHoleBorders ; bool bOk = GetTrimmingHoleBorders( vpSurfs, ptRef, dSurfLinTol, dSurfAngTol, dEdgeLinTol, dEdgeAngTol, dEdgeThick, vHoleBorders) ; if ( bOk) { // Inserisco le curve nel DB e imposto i parametri di ritorno bool bFirst = true ; for ( int i = 0 ; bOk && i < ssize( vHoleBorders) ; ++ i) { // Verifico che sia valida if ( ! IsNull( vHoleBorders[i]) && vHoleBorders[i]->IsValid()) { int nCrvId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vHoleBorders[i])) ; bOk = ( nCrvId != GDB_ID_NULL) ; if ( bOk) { ++ nCount ; if ( bFirst) { nFirstId = nCrvId ; bFirst = false ; } } } } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetHoleBorder(" + ToString( nParentId) + "," + ToString( vSurfIds) + "," + ToString( dSurfLinTol) + "," + ToString( dSurfAngTol) + "," + ToString( dEdgeLinTol) + "," + ToString( dEdgeAngTol) + "," + ToString( dEdgeThick) + ")" + " bOk=" + ToString( bOk) + " nNewSurfId=" + ToString( nFirstId) + ", nCount= " + ToString( nCount) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- int ExeTrimmingGetSurfTmFaceAdj( int nParentId, int nSurfId, int nTria, const Point3d& ptTria, double dAngTol, double dSize, double dSizeTol) { // 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()) ; // Recupero la superficie formata dai triangoli di adiacenza int nNewSurfId = GDB_ID_NULL ; if ( bOk) { PtrOwner pStmAdjFace( CreateSurfTriMesh()) ; bOk = ( ! IsNull( pStmAdjFace) && pStmAdjFace->AdjustTopology()) ; bOk = GetTrimmingStmAdjTria( pStm, nTria, ptTria, dAngTol, dSize, dSizeTol, pStmAdjFace) ; bOk = ( ! IsNull( pStmAdjFace) && pStmAdjFace->IsValid() && pStmAdjFace->GetTriangleCount() > 0) ; // Inserisco la Superficie nel DB geometrico if ( bOk) { nNewSurfId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pStmAdjFace)) ; bOk = ( nNewSurfId != GDB_ID_NULL) ; } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetSurfTmFromFaceAdj(" + ToString( nParentId) + "," + ToString( nSurfId) + "," + ToString( nTria) + "," + "{ " + ToString( ptTria.x) + "," + ToString( ptTria.y) + "," + ToString( ptTria.z) + "}," + ToString( dAngTol) + ")" + " nNewSurfId=" + ToString( nNewSurfId) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return nNewSurfId ; } // --------------------------------------------------------------------------- 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 ( 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 dSurfLinTol, double dSurfAngTol, 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, dSurfLinTol, dSurfAngTol, 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( dSurfLinTol) + "," + ToString( dSurfAngTol) + "," + 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 dSurfLinTol, double dSurfAngTol, double dLinTol, double dAngTol, double dThick, 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, dSurfLinTol, dSurfAngTol, dLinTol, dAngTol, dThick, vBezierEdges) ; if ( bOk) { 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 ; } } 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())) ; for ( int i = 0 ; bOk && i < ssize( vnLineId) ; ++ i) { // Recupero la Curva const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( vnLineId[i])) ; bOk = bOk && ( pLine != nullptr && pLine->IsValid()) ; if ( bOk) { // Recupero gli Estremi Point3d ptStart ; pLine->GetStartPoint( ptStart) ; Point3d ptEnd ; pLine->GetEndPoint( ptEnd) ; // Mi assicuro che gli estremi siano sulle curve di Bordo e orientati correttamente ( nel caso inverto) double dSqDistS1 = INFINITO ; if ( ! DistPointCurve( ptStart, *pCrvEdge1).GetSqDist( dSqDistS1)) continue ; if ( dSqDistS1 < dLinTol * dLinTol) { double dSqDistE2 = INFINITO ; if ( ! DistPointCurve( ptEnd, *pCrvEdge2).GetSqDist( dSqDistE2) || dSqDistE2 > dLinTol * dLinTol) continue ; } else { double dSqDistS2 = INFINITO ; if ( ! DistPointCurve( ptStart, *pCrvEdge2).GetSqDist( dSqDistS2) || dSqDistS2 > dLinTol * dLinTol) continue ; double dSqDistE1 = INFINITO ; if ( ! DistPointCurve( ptEnd, *pCrvEdge1).GetSqDist( dSqDistE1) || dSqDistE1 > dLinTol * dLinTol) continue ; swap( ptStart, ptEnd) ; } vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; } } // Recupero la superficie Bezier rigata PtrOwner pSurfBzRuled ; if ( bOk) { pSurfBzRuled.Set( GetTrimmingRuledBezier( vpSurf, pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints)) ; 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 ExeTrimmingInterpolateSyncLines( int nParentId, int nSync1Id, int nSync2Id, int nBorder1Id, int nBorder2Id, double dEdgeLinTol, double dEdgeAngTol, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) // Reset parametri di ritorno nFirstId = GDB_ID_NULL ; nCount = 0 ; // Aggiusto la tolleranza lineare e angolare se necessario double dMyEdgeLinTol = Clamp( dEdgeLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; double dMyEdgeAngTol = Clamp( dEdgeAngTol, EPS_ANG_SMALL, 60.) ; // recupero le due curve di sincronizzazione const ICurve* pSync1 = GetCurve( pGeomDB->GetGeoObj( nSync1Id)) ; const ICurve* pSync2 = GetCurve( pGeomDB->GetGeoObj( nSync2Id)) ; bool bOk = ( pSync1 != nullptr && pSync1->IsValid() && pSync2 != nullptr && pSync2->IsValid()) ; // Recupero le due curve di bordo const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nBorder1Id)) ; const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nBorder2Id)) ; bOk = bOk && ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid()) ; bOk = bOk && ( pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ; // Calcolo le Curve di sincornizzazione Interpolate BIPNTVECTOR vSyncPoints ; bOk = bOk && GetTrimmingSyncInterpolation( pCrvEdge1, pCrvEdge2, pSync1, pSync2, dMyEdgeLinTol, dMyEdgeAngTol, vSyncPoints) ; if ( bOk && ! vSyncPoints.empty()) { // Inserisco le curve di sincronizzazione nel DB // [orientate da pCrvEdge1 a pCrvEdge2] for ( int i = 0 ; bOk && i < ssize( vSyncPoints) ; ++ i) { PtrOwner pSyncLine( CreateCurveLine()) ; bOk = ( ! IsNull( pSyncLine) && pSyncLine->Set( vSyncPoints[i].first, vSyncPoints[i].second)) ; if ( bOk) { if ( pCrvEdge1->IsPointOn( vSyncPoints[i].second, dMyEdgeLinTol)) pSyncLine->Invert() ; int nSyncId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pSyncLine)) ; bOk = ( nSyncId != CMD_ID_NULL) ; if ( i == 0) nFirstId = nSyncId ; } } nCount = ssize( vSyncPoints) ; } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingInterpolateSyncLines(" + ToString( nParentId) + "," + ToString( nSync1Id) + "," + ToString( nSync2Id) + "," + ToString( nBorder1Id) + "," + ToString( nBorder2Id) + "," + ToString( dEdgeLinTol) + "," + ToString( dEdgeAngTol) + ")" + " -- bOk=" + ToString( bOk) + " -- nFirstId=" + ToString( nFirstId) + " nCount=" + ToString( nCount) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- bool ExeTrimmingGetSurfBzSyncPoints( int nParentId, int nEdge1Id, int nEdge2Id, double dLinTol, double dAngTol, int nLineNbr, bool bShowOnCorners, int& nFirstId, int& nCount) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Imposto i parametri di ritorno nFirstId = GDB_ID_NULL ; nCount = 0 ; // Se non devo visualizzare alcuna linea, non faccio nulla if ( nLineNbr <= 0 && ! bShowOnCorners) return true ; // Se necessario aggiusto le tolleranze double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, ANG_RIGHT) ; // 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()) ; // Verifico che le curve siano entrambe Aperte o entrambe Chiuse bOk = bOk && ( pCrvEdge1->IsClosed() == pCrvEdge2->IsClosed()) ; // Recupero i punti di sincronizzazione BIPNTVECTOR vSyncPoints ; bOk = bOk && GetTrimmingSurfBzSyncPoints( pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints) && ( ! vSyncPoints.empty()) ; int nToTSyncLines = ssize( vSyncPoints) ; // Ogni punto di sincronizzazione deve avere gli estremi sulle curve di Bordo for ( int i = 0 ; bOk && i < ssize( vSyncPoints) ; ++ i) { double dSqDistStart = INFINITO, dSqDistEnd = INFINITO ; bOk = ( DistPointCurve( vSyncPoints[i].first, *pCrvEdge1).GetSqDist( dSqDistStart) && dSqDistStart < dMyLinTol * dMyLinTol && DistPointCurve( vSyncPoints[i].second, *pCrvEdge2).GetSqDist( dSqDistEnd) && dSqDistEnd < dMyLinTol * dMyLinTol) ; } if ( bOk) { INTSET setInds ; // Se devo visualizzare più linee di quante ne ho ricavate, allora le devo visualizzare tutte if ( nLineNbr >= nToTSyncLines) { for ( int i = 0 ; i < nToTSyncLines ; ++ i) setInds.insert( i) ; } // Altrimenti else { // Se voglio visualizzare gli Spigoli if ( bShowOnCorners) { for ( int nL = 0 ; bOk && nL < nToTSyncLines ; ++ nL) { // Controllo se punto su spigolo della curva double dU = 0. ; Vector3d vtTanPrev, vtTanAft ; Point3d ptUseless ; bOk = ( pCrvEdge1->GetParamAtPoint( vSyncPoints[nL].first, dU, dMyLinTol) && pCrvEdge1->GetPointD1D2( dU, ICurve::FROM_MINUS, ptUseless, &vtTanPrev) && pCrvEdge1->GetPointD1D2( dU, ICurve::FROM_PLUS, ptUseless, &vtTanAft)) ; if ( ! bOk) break ; vtTanPrev.Normalize() ; vtTanAft.Normalize() ; if ( vtTanPrev * vtTanAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) { setInds.insert( nL) ; continue ; } bOk = ( pCrvEdge2->GetParamAtPoint( vSyncPoints[nL].second, dU, dMyLinTol) && pCrvEdge2->GetPointD1D2( dU, ICurve::FROM_MINUS, ptUseless, &vtTanPrev) && pCrvEdge2->GetPointD1D2( dU, ICurve::FROM_PLUS, ptUseless, &vtTanAft)) ; if ( ! bOk) break ; vtTanPrev.Normalize() ; vtTanAft.Normalize() ; if ( vtTanPrev * vtTanAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) { setInds.insert( nL) ; continue ; } } } // Se devo mostrare alcune Linee if ( bOk && nLineNbr > 0) { bool bBothOpen = ( ! pCrvEdge1->IsClosed() && ! pCrvEdge2->IsClosed()) ; bool bBothClosed = ( ! bBothOpen) ; int nLastIdx = nToTSyncLines - 1 ; if ( bBothClosed) { int nLine = nLineNbr ; if ( nLine == 1) setInds.insert( 0) ; else { int nMaxIndex = nToTSyncLines - 2 ; for ( int i = 0 ; i < nLine ; ++ i) { double dT = double( i) / double( nLine) ; int nIdx = int( 0.5 + dT * nMaxIndex) ; setInds.insert( nIdx) ; } setInds.erase( nLastIdx) ; } } else { int nInternal = nLineNbr ; setInds.insert( 0) ; setInds.insert( nLastIdx) ; int nMaxIndex = nLastIdx ; for ( int i = 0; i < nInternal ; ++ i) { double dT = double( i + 1) / double( nInternal + 1) ; int nIdx = int( 0.5 + dT * nMaxIndex) ; setInds.insert( nIdx) ; } } } } // Visualizzo i segmenti lineari di sincronizzazione per ogni indice ricavato bool bFirst = true ; for ( auto Iter = setInds.begin() ; bOk && Iter != setInds.end() ; ++ Iter) { PtrOwner pLine( CreateCurveLine()) ; bOk = ( ! IsNull( pLine) && pLine->Set( vSyncPoints[*Iter].first, vSyncPoints[*Iter].second)) ; if ( bOk) { int nLineId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ; bOk = ( nLineId != GDB_ID_NULL) ; if ( bFirst) { nFirstId = nLineId ; bFirst = false ; } ++ nCount ; } } } 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 ExeTrimmingGetToolOrientationLines( int nParentId, int nMainEdgeId, int nOtherEdgeId, int nSyncLayerId, int nLineSId, int nLineEId, double dThetaStart, double dPhiStart, double dThetaEnd, double dPhiEnd, double dInterpLenS, double dInterpLenE, double dLinTol, int& nInterpStartId, int& nStartId, int& nEndId, int& nInterpEndId) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Imposto i parametri di ritorno nInterpStartId = GDB_ID_NULL, nStartId = GDB_ID_NULL, nEndId = GDB_ID_NULL, nInterpEndId = GDB_ID_NULL ; // Se necessario aggiusto le tolleranze double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; const double TOL = dMyLinTol ; // Definisco costanti per interpolazione const double INTERPOLATION_DIST = 0.5 ; // alzare const double ISO_PAR_SAMPLE = 20.0 ; // Recupero il riferimento del gruppo di destinazione Frame3d frDest ; bool bOk = ( pGeomDB->GetGlobFrame( nParentId, frDest)) ; // Recupero le due Curve di bordo const ICurve* pCrvMainEdge = GetCurve( pGeomDB->GetGeoObj( nMainEdgeId)) ; const ICurve* pCrvOtherEdge = GetCurve( pGeomDB->GetGeoObj( nOtherEdgeId)) ; bOk = bOk && ( pCrvMainEdge != nullptr && pCrvMainEdge->IsValid() && pCrvOtherEdge != nullptr && pCrvOtherEdge->IsValid()) ; // Verifico che le curve siano entrambe Aperte o entrambe Chiuse e memorizzo il risultato bOk = bOk && ( pCrvMainEdge->IsClosed() == pCrvOtherEdge->IsClosed()) ; bool bBorderClosed = ( pCrvMainEdge->IsClosed()) ; // Recupero le Linee di Sincronizzazione iniziali e finali e verifico che giacciano sulle Curve di Bordo PtrOwner pCrvSyncS( GetCurve( pGeomDB->GetGeoObj( nLineSId))->Clone()) ; PtrOwner pCrvSyncE( GetCurve( pGeomDB->GetGeoObj( nLineEId))->Clone()) ; bOk = bOk && ( pCrvSyncS != nullptr && pCrvSyncS->IsValid() && pCrvSyncE != nullptr && pCrvSyncE->IsValid()) ; BIPOINT Line1, Line2 ; bOk = bOk && ( pCrvSyncS->GetStartPoint( Line1.first)) && ( pCrvSyncS->GetEndPoint( Line1.second)) ; bOk = bOk && ( pCrvSyncE->GetStartPoint( Line2.first)) && ( pCrvSyncE->GetEndPoint( Line2.second)) ; // --- se necessario oriento le linee di Sync in modo che inizino entrambe dal Bordo Main if ( bOk) { if ( pCrvMainEdge->IsPointOn( Line1.first, TOL)) bOk = ( pCrvOtherEdge->IsPointOn( Line1.second, TOL)) ; else if ( pCrvOtherEdge->IsPointOn( Line1.first, TOL)) { bOk = ( pCrvMainEdge->IsPointOn( Line1.second, TOL)) ; if ( bOk) { swap( Line1.first, Line1.second) ; pCrvSyncS->Invert() ; } } else bOk = false ; } if ( bOk) { if ( pCrvMainEdge->IsPointOn( Line2.first, TOL)) bOk = ( pCrvOtherEdge->IsPointOn( Line2.second, TOL)) ; else if ( pCrvOtherEdge->IsPointOn( Line2.first, TOL)) { bOk = ( pCrvMainEdge->IsPointOn( Line2.second, TOL)) ; if ( bOk) { swap( Line2.first, Line2.second) ; pCrvSyncE->Invert() ; } } else bOk = false ; } // Il percorso selezionato è il minore tra le due possibilità di percorrenza if ( bOk && bBorderClosed) { double dParS = 0. ; PtrOwner pCompoMainCL( ConvertCurveToComposite( pCrvMainEdge->Clone())) ; bOk = ( ! IsNull( pCompoMainCL) && pCompoMainCL->IsValid() && pCompoMainCL->GetParamAtPoint( Line1.first, dParS, TOL)) ; if ( bOk) { pCompoMainCL->ChangeStartPoint( dParS) ; double dLenE = 0., dLenMain = 0. ; bOk = ( pCompoMainCL->GetLengthAtPoint( Line2.first, dLenE, TOL) && pCompoMainCL->GetLength( dLenMain)) ; if ( dLenE > dLenMain / 2. + EPS_SMALL) { swap( Line1, Line2) ; swap( pCrvSyncS, pCrvSyncE) ; } } } // Calcolo la lunghezza delle due curve di Bordo double dLenMain = 0., dLenOther = 0. ; bOk = bOk && ( pCrvMainEdge->GetLength( dLenMain) && pCrvOtherEdge->GetLength( dLenOther) && dLenMain > 2. * TOL + dInterpLenS + dInterpLenE + EPS_SMALL && dLenOther > 2. * TOL + dInterpLenS + dInterpLenE + EPS_SMALL) ; // Recupero i punti di sincronizzazione (se presenti) BIPNTVECTOR vSyncPoints ; vSyncPoints.reserve( pGeomDB->GetGroupObjs( nSyncLayerId)) ; int nLineId = pGeomDB->GetFirstInGroup( nSyncLayerId) ; while ( bOk && nLineId != GDB_ID_NULL) { // Recupero la Curva const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( nLineId)) ; bOk = bOk && ( pLine != nullptr && pLine->IsValid()) ; if ( bOk) { // Recupero gli Estremi Point3d ptStart ; pLine->GetStartPoint( ptStart) ; Point3d ptEnd ; pLine->GetEndPoint( ptEnd) ; // Mi assicuro che gli estremi siano sulle curve di Bordo ( in un verso o nell'altro, mantengo il verso) double dDistS1 = INFINITO ; if ( ! DistPointCurve( ptStart, *pCrvMainEdge).GetDist( dDistS1)) { nLineId = pGeomDB->GetNext( nLineId) ; continue ; } if ( dDistS1 < dLinTol) { double dDistE2 = INFINITO ; if ( ! DistPointCurve( ptEnd, *pCrvOtherEdge).GetDist( dDistE2) || dDistE2 > dLinTol) { nLineId = pGeomDB->GetNext( nLineId) ; continue ; } } else { double dDistS2 = INFINITO ; if ( ! DistPointCurve( ptStart, *pCrvOtherEdge).GetDist( dDistS2) || dDistS2 > dLinTol) { nLineId = pGeomDB->GetNext( nLineId) ; continue ; } double dDistE1 = INFINITO ; if ( ! DistPointCurve( ptEnd, *pCrvMainEdge).GetDist( dDistE1) || dDistE1 > dLinTol) { nLineId = pGeomDB->GetNext( nLineId) ; continue ; } } vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; } nLineId = pGeomDB->GetNext( nLineId) ; } // Recupero la superficie Bezier rigata PtrOwner pSurfBzRuled ; if ( bOk) { // Se non ho linee di sincronizzazione if ( vSyncPoints.empty()) pSurfBzRuled.Set( GetSurfBezierRuledSmooth( pCrvMainEdge, pCrvOtherEdge, vSyncPoints, ISO_PAR_SAMPLE)) ; // Se ho linee di sincronizzazione else pSurfBzRuled.Set( GetSurfBezierRuledGuided( pCrvMainEdge, pCrvOtherEdge, vSyncPoints, dMyLinTol)) ; bOk = bOk && ( ! IsNull( pSurfBzRuled) && pSurfBzRuled->IsValid()) ; } // --- Calcolo delle Linee di Orientamento --- if ( bOk) { // Rotazione delle curve di Bordo rispetto al Bordo Main double dLenS ; pCrvSyncS->GetLength( dLenS) ; Line1.second = Line1.first + FromSpherical( dLenS, dThetaStart, dPhiStart) ; double dLenE ; pCrvSyncE->GetLength( dLenE) ; Line2.second = Line2.first + FromSpherical( dLenE, dThetaEnd, dPhiEnd) ; // --- Eventuale Interpolazione Lineare di Raccordo all'Inizio --- if ( dInterpLenS > TOL) { double dExtension = dInterpLenS ; double dLen = -1. ; pCrvMainEdge->GetLengthAtPoint( Line1.first, dLen, TOL) ; if ( bBorderClosed) { dLen -= dInterpLenS ; if ( dLen < EPS_SMALL) dLen = dLenMain + dLen ; } else { if ( dLen < dInterpLenS - EPS_SMALL) { dExtension = dLen ; dLen = 0 ; } } double dU = - 1; bOk = pCrvMainEdge->GetParamAtLength( dLen, dU) ; if ( bOk) { // Definisco la linea si sincronizzazione Point3d ptInterpS ; double dParU, dParV ; PtrOwner pCompoIso( nullptr) ; BIPOINT LineInterpS ; bOk = ( pCrvMainEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptInterpS) && DistPointSurfBz( ptInterpS, *pSurfBzRuled).GetParamsAtMinDistPoint( dParU, dParV) && pCompoIso.Set( pSurfBzRuled->GetCurveOnV( dParU)) && pCompoIso->IsValid() && pCompoIso->GetStartPoint( LineInterpS.first) && pCompoIso->GetEndPoint( LineInterpS.second)) ; if ( bOk) { bool bFirst = true ; // Interpolo double dLenLineInterpS = Dist( LineInterpS.first, LineInterpS.second) ; double dLenLine1 = Dist( Line1.first, Line1.second) ; int nStep = max( 1, int( ceil( dExtension / INTERPOLATION_DIST))) ; Vector3d vtInterpStart = ( LineInterpS.second - LineInterpS.first) ; vtInterpStart.Normalize() ; Vector3d vtInterpEnd = ( Line1.second - Line1.first) ; vtInterpEnd.Normalize() ; Vector3d vtDiff = vtInterpEnd - vtInterpStart ; for ( int i = 0 ; bOk && i < ( nStep - 1) ; ++ i) { // ( nStep - 1) per evitare sovrapposizione con la Copia del vettore double dI = double( i) ; Vector3d vtInterp = vtInterpStart + ( dI / ( nStep - 1)) * vtDiff ; double dUInterpMain = 0. ; Point3d ptInterpOnMain ; double dCurrLen = dLen + ( dI * dExtension / ( nStep - 1)) ; if ( dCurrLen > dLenMain) dCurrLen -= dLenMain ; bOk = ( pCrvMainEdge->GetParamAtLength( dCurrLen, dUInterpMain) && pCrvMainEdge->GetPointD1D2( dUInterpMain, ICurve::FROM_MINUS, ptInterpOnMain)) ; if ( bOk) { double dMagnitude = dLenLineInterpS + ( dI / ( nStep - 1)) * ( dLenLine1 - dLenLineInterpS) ; PtrOwner pLine( CreateCurveLine()) ; bOk = ( ! IsNull( pLine) && pLine->Set( ptInterpOnMain, ptInterpOnMain + vtInterp * dMagnitude)) ; if ( bOk) { int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ; bOk = ( nNewId != GDB_ID_NULL) ; if ( bOk) { if ( bFirst) { nInterpStartId = nNewId ; bFirst = false ; } } } } } } } } // --- Interpolazione tra le due Linee di Sincronizzazione --- if ( bOk) { double dLenS = -1., dLenE = -1 ; bOk = ( pCrvMainEdge->GetLengthAtPoint( Line1.first, dLenS, TOL) && pCrvMainEdge->GetLengthAtPoint( Line2.first, dLenE, TOL)) ; if ( bOk) { double dToTDist = 0. ; if ( dLenS < dLenE) dToTDist = dLenE - dLenS ; else dToTDist = ( dLenMain - dLenS) + dLenE ; if ( dToTDist > TOL) { bool bFirst = true ; // Interpolo double dLenLine1 = Dist( Line1.first, Line1.second) ; double dLenLine2 = Dist( Line2.first, Line2.second) ; int nStep = max( 1, int( ceil( dToTDist / INTERPOLATION_DIST))) ; Vector3d vtLineS = ( Line1.second - Line1.first) ; vtLineS.Normalize() ; Vector3d vtLineE = ( Line2.second - Line2.first) ; vtLineE.Normalize() ; Vector3d vtDiff = ( vtLineE - vtLineS) ; for ( int i = 0 ; bOk && i <= nStep ; ++ i) { double dI = double( i) ; Vector3d vtInterp = vtLineS + ( dI / nStep) * vtDiff ; double dUInterpMain = 0. ; Point3d ptInterpOnMain ; double dCurrLen = dLenS + ( dI * dToTDist / nStep) ; if ( dCurrLen > dLenMain) dCurrLen -= dLenMain ; bOk = ( pCrvMainEdge->GetParamAtLength( dCurrLen, dUInterpMain) && pCrvMainEdge->GetPointD1D2( dUInterpMain, ICurve::FROM_MINUS, ptInterpOnMain)) ; if ( bOk) { double dMagnitude = dLenLine1 + ( dI / nStep) * ( dLenLine2 - dLenLine1) ; PtrOwner pLine( CreateCurveLine()) ; bOk = ( ! IsNull( pLine) && pLine->Set( ptInterpOnMain, ptInterpOnMain + vtInterp * dMagnitude)) ; if ( bOk) { int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ; bOk = ( nNewId != GDB_ID_NULL) ; if ( bOk) { if ( bFirst) { nStartId = nNewId ; bFirst = false ; } nEndId = nNewId ; } } } } } } } // --- Eventuale Interpolazione Lineare di Raccordo alla Fine --- if ( bOk && dInterpLenE > TOL) { double dExtension = dInterpLenE ; double dLen = -1. ; pCrvMainEdge->GetLengthAtPoint( Line2.first, dLen, TOL) ; if ( bBorderClosed) { dLen += dInterpLenE ; if ( dLen > dLenMain - EPS_SMALL) dLen -= dLenMain ; } else { if ( dLen > dLenMain - dInterpLenE - EPS_SMALL) { dExtension = dLenMain - dLen ; dLen = dLenMain ; } } double dU = - 1 ; bOk = pCrvMainEdge->GetParamAtLength( dLen, dU) ; if ( bOk) { // Definisco la linea si sincronizzazione Point3d ptInterpE ; double dParU, dParV ; PtrOwner pCompoIso( nullptr) ; BIPOINT LineInterpE ; bOk = ( pCrvMainEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptInterpE) && DistPointSurfBz( ptInterpE, *pSurfBzRuled).GetParamsAtMinDistPoint( dParU, dParV) && pCompoIso.Set( pSurfBzRuled->GetCurveOnV( dParU)) && pCompoIso->IsValid() && pCompoIso->GetStartPoint( LineInterpE.first) && pCompoIso->GetEndPoint( LineInterpE.second)) ; if ( bOk) { // Interpolo double dLenLineInterpE = Dist( LineInterpE.first, LineInterpE.second) ; double dLenLine2 = Dist( Line2.first, Line2.second) ; int nStep = max( 1, int( ceil( dExtension / INTERPOLATION_DIST))) ; Vector3d vtInterpStart = ( Line2.second - Line2.first) ; vtInterpStart.Normalize() ; Vector3d vtInterpEnd = ( LineInterpE.second - LineInterpE.first) ; vtInterpEnd.Normalize() ; Vector3d vtDiff = vtInterpEnd - vtInterpStart ; for ( int i = 1 ; bOk && i < nStep ; ++ i) { // i = 1 per evitare la sopvrapposizione con la Copia del vettore double dI = double( i) ; Vector3d vtInterp = vtInterpStart + ( dI / ( nStep - 1)) * vtDiff ; double dUInterpMain = 0. ; Point3d ptInterpOnMain ; double dCurrLen = ( dLen - dExtension) + ( dI * dExtension / ( nStep - 1)) ; if ( dCurrLen > dLenMain) dCurrLen -= dLenMain ; bOk = ( pCrvMainEdge->GetParamAtLength( dCurrLen, dUInterpMain) && pCrvMainEdge->GetPointD1D2( dUInterpMain, ICurve::FROM_MINUS, ptInterpOnMain)) ; if ( bOk) { double dMagnitude = dLenLine2 + ( dI / ( nStep - 1)) * ( dLenLineInterpE - dLenLine2) ; PtrOwner pLine( CreateCurveLine()) ; bOk = ( ! IsNull( pLine) && pLine->Set( ptInterpOnMain, ptInterpOnMain + vtInterp * dMagnitude)) ; if ( bOk) { int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ; bOk = ( nNewId != GDB_ID_NULL) ; if ( bOk) nInterpEndId = nNewId ; } } } } } } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetToolOrientationLines(" + ToString( nParentId) + "," + ToString( nMainEdgeId) + "," + ToString( nOtherEdgeId) + "," + ToString( nLineSId) + "," + ToString( nLineEId) + "," + ToString( dThetaStart) + "," + ToString( dPhiStart) + "," + ToString( dThetaEnd) + "," + ToString( dPhiEnd) + "," + ToString( dLinTol) + "," + ToString( dInterpLenS) + "," + ToString( dInterpLenE) + "," + " -- bOk=" + ToString( bOk) + " -- nInterpStartId=" + ToString( nInterpStartId) + ", nStartId=" + ToString( nStartId) + ", nEndId=" + ToString( nEndId) + ", nInterpEndId=" + ToString( nInterpEndId) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- struct TrimmingInterval { double dLenStart ; double dLenEnd ; Vector3d vtStart ; Vector3d vtEnd ; TrimmingInterval() : dLenStart( - EPS_SMALL), dLenEnd( - EPS_SMALL), vtStart( V_INVALID), vtEnd( V_INVALID) {} ; TrimmingInterval( double dLenS, double dLenE, const Vector3d& vtS, const Vector3d& vtE) : dLenStart( dLenS), dLenEnd( dLenE), vtStart( vtS), vtEnd( vtE) {} ; } ; typedef vector TRIMMINGINTERVALVECTOR ; // --------------------------------------------------------------------------- bool GetTrimmingInterval( const IGeomDB* pGeomDB, const ICurveComposite* pCompo, const Frame3d& frCompo, int nIdS, int nIdE, bool bInvert, TrimmingInterval& TrimmingInt) { // Verifico validità dei parametri VERIFY_GEOMDB( pGeomDB, false) if ( pCompo == nullptr || ! pCompo->IsValid() || ! frCompo.IsValid()) return false ; // Recupero le linee di Orienting const ICurve* pGeoCrvS = GetCurve( pGeomDB->GetGeoObj( nIdS)) ; const ICurve* pGeoCrvE = GetCurve( pGeomDB->GetGeoObj( nIdE)) ; if ( pGeoCrvS != nullptr && pGeoCrvE != nullptr && pGeoCrvS->IsValid() && pGeoCrvE->IsValid()) { // Recupero i punti base ches stanno sulla pCompo e i vettori direzioni ( sono ICurveLine*, ma le tratto come ICurve* generiche) Point3d ptS = P_INVALID ; Point3d ptE = P_INVALID ; if ( ! bInvert) { pGeoCrvS->GetStartPoint( ptS) ; // Line1.ptStart pGeoCrvE->GetStartPoint( ptE) ; // Line2.ptStart } else { pGeoCrvS->GetEndPoint( ptS) ; pGeoCrvE->GetEndPoint( ptE) ; } Vector3d vtS = V_INVALID ; pGeoCrvS->GetStartDir( vtS) ; // Line1.vtStart Vector3d vtE = V_INVALID ; pGeoCrvE->GetStartDir( vtE) ; // Line2.vtStart if ( ptS.IsValid() && ptE.IsValid() && vtS.IsValid() && vtE.IsValid()) { // Recupero il Frame delle Linee Frame3d frCrv1, frCrv2 ; if ( ! pGeomDB->GetGlobFrame( nIdS, frCrv1) || ! pGeomDB->GetGlobFrame( nIdE, frCrv2)) return false ; // Porto Tali valori nel riferimento dalla Composita Point3d ptSLoc = GetLocToLoc( ptS, frCrv1, frCompo) ; Point3d ptELoc = GetLocToLoc( ptE, frCrv2, frCompo) ; Vector3d vtSLoc = GetLocToLoc( vtS, frCrv1, frCompo) ; Vector3d vtELoc = GetLocToLoc( vtE, frCrv2, frCompo) ; // Recupero il parametro sulla curva double dParS = - EPS_PARAM, dParE = - EPS_PARAM ; int nFlag = 0 ; if ( DistPointCurve( ptSLoc, *pCompo).GetParamAtMinDistPoint( EPS_SMALL, dParS, nFlag) && DistPointCurve( ptELoc, *pCompo).GetParamAtMinDistPoint( EPS_SMALL, dParE, nFlag)) { // Recupero la lunghezza su tale curva double dLenS = - EPS_SMALL, dLenE = - EPS_SMALL ; if ( pCompo->GetLengthAtParam( dParS, dLenS) && pCompo->GetLengthAtParam( dParE, dLenE)) { TrimmingInt = TrimmingInterval( dLenS, dLenE, vtSLoc, vtELoc) ; return true ; } } } } return false ; } // --------------------------------------------------------------------------- bool Exe5AxTrimmingModifyToolDir( int nCrvId, int nPathId, int nTrimLayId, const INTVECTOR& vnOrientingId, const INTVECTOR& vnOrientingISId, const INTVECTOR& vnOrientingSId, const INTVECTOR& vnOrientingEId, const INTVECTOR& vnOrientingIEId) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Verifico validità dei parametri bool bOk = ( nCrvId != GDB_ID_NULL && nPathId != GDB_ID_NULL && nTrimLayId != GDB_ID_NULL && ssize( vnOrientingId) == ssize( vnOrientingISId) && ssize( vnOrientingISId) == ssize( vnOrientingSId) && ssize( vnOrientingSId) == ssize( vnOrientingEId) && ssize( vnOrientingEId) == ssize( vnOrientingIEId)) ; // Recupero la curva di Bordo e la sua composit associata const ICurve* pCrvBorder = GetCurve( pGeomDB->GetGeoObj( nCrvId)) ; bOk = bOk && ( pCrvBorder != nullptr && pCrvBorder->IsValid()) ; PtrOwner pCompoBorder( nullptr) ; if ( bOk) bOk = ( pCompoBorder.Set( ConvertCurveToComposite( pCrvBorder->Clone())) && pCompoBorder->IsValid()) ; double dLen = - EPS_SMALL ; if ( bOk) bOk = pCompoBorder->GetLength( dLen) ; // Recupero il Frame della curva corrente Frame3d frCompo ; bOk = bOk && ( pGeomDB->GetGlobFrame( nCrvId, frCompo)) ; bool bInvert = false ; if ( ssize( vnOrientingISId) > 0 && vnOrientingISId[0] != GDB_ID_NULL) { const ICurve* pGeoCrvS = GetCurve( pGeomDB->GetGeoObj( vnOrientingISId[0])) ; Point3d ptS ; pGeoCrvS->GetStartPoint( ptS) ; double dDist = 1 ; if ( DistPointCurve( ptS, *pCompoBorder).GetDist( dDist) && dDist > EPS_SMALL) bInvert = true ; } // Recupero i versori di interpolazione e creo dei gruppi TRIMMINGINTERVALVECTOR vInterval ; vInterval.reserve( 3 * ssize( vnOrientingId)) ; for ( int i = 0 ; bOk && i < ssize( vnOrientingId) ; ++ i) { // Se presente Interpolazione iniziale if ( vnOrientingISId[i] != GDB_ID_NULL && vnOrientingSId[i] != GDB_ID_NULL) { TrimmingInterval myTrimInt ; if ( GetTrimmingInterval( pGeomDB, pCompoBorder, frCompo, vnOrientingISId[i], vnOrientingSId[i], bInvert, myTrimInt)) vInterval.emplace_back( myTrimInt) ; } // Interpolazione ( deve essere sempre presente, ma per scrupolo si controlla lo stesso) if ( vnOrientingSId[i] != GDB_ID_NULL && vnOrientingEId[i] != GDB_ID_NULL) { TrimmingInterval myTrimInt ; if ( GetTrimmingInterval( pGeomDB, pCompoBorder, frCompo, vnOrientingSId[i], vnOrientingEId[i], bInvert, myTrimInt)) vInterval.emplace_back( myTrimInt) ; } // Se presente Interpolazione finale if ( vnOrientingEId[i] != GDB_ID_NULL && vnOrientingIEId[i] != GDB_ID_NULL) { TrimmingInterval myTrimInt ; if ( GetTrimmingInterval( pGeomDB, pCompoBorder, frCompo, vnOrientingEId[i], vnOrientingIEId[i], bInvert, myTrimInt)) vInterval.emplace_back( myTrimInt) ; } } // Se ho degli intervalli di Interpolazione if ( ! vInterval.empty()) { // Scorro i vettori presenti nel Layer ausiliario della lavorazione int nId = pGeomDB->GetFirstInGroup( nPathId) ; while ( bOk && nId != GDB_ID_NULL) { IGeoVector3d* vGeo = GetGeoVector3d( pGeomDB->GetGeoObj( nId)) ; if ( vGeo != nullptr && vGeo->IsValid()) { // Recupero i parametri di tale vettore Point3d ptBase = vGeo->GetBase() ; Vector3d vtDirV = V_INVALID ; ; if ( pGeomDB->GetInfo( nId, "DirV", vtDirV) && vtDirV.IsValid()) { // Recupero la lunghezza associata al Punto di Base sulla Compo double dCurrPar = - EPS_SMALL ; int nFlag = 0 ; if ( DistPointCurve( ptBase, *pCompoBorder).GetParamAtMinDistPoint( 0., dCurrPar, nFlag)) { double dCurrLen = - EPS_SMALL ; if ( pCompoBorder->GetLengthAtParam( dCurrPar, dCurrLen)) { for ( const TrimmingInterval& CurrInterval : vInterval) { // Controlli per Intervalli a cavallo dei punti iniziali e finali della curva double dLenA = CurrInterval.dLenStart ; double dLenB = CurrInterval.dLenEnd ; double dLenC = dCurrLen ; if ( dLenA > dLenB) { dLenB += dLen ; if ( dLenC < CurrInterval.dLenStart - EPS_SMALL) dLenC += dLen ; } // Se l'intervallo non è troppo piccolo e se sono all'interno di tale Intervallo if ( dLenB - dLenA > 10. * EPS_SMALL && /* bastava anche 2 * EPS_SMALL */ dLenA + EPS_SMALL < dLenC && dLenC < dLenB + EPS_SMALL /* estremi esclusi, va bene ? */) { // Media pesata dei due vettori double dMeanPar = ( dLenC - dLenA) / ( dLenB - dLenA) ; Vector3d vtMean = Media( CurrInterval.vtStart, CurrInterval.vtEnd, dMeanPar) ; // Assegno la Info a tale vettore pGeomDB->SetInfo( nId, "DirV", vtMean) ; break ; // non controllo altri intervalli } } } } } } nId = pGeomDB->GetNext( nId) ; } } ExeSetModified() ; // Se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtTrimmingGetToolOrientationLines(" + ToString( nCrvId) + "," + ToString( nPathId) + "," + ToString( nTrimLayId) + "," + ToString( vnOrientingId) + "," + ToString( vnOrientingISId) + "," + ToString( vnOrientingSId) + "," + ToString( vnOrientingEId) + "," + ToString( vnOrientingIEId) + "," + " -- bOk=" + ToString( bOk) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } return bOk ; } // --------------------------------------------------------------------------- int ExeRegolarizeSurfaceLocally( int nParentId, int nSurfId, int nSyncStartId, int nSyncEndId, double dLinTol, int nType) { // Verifica database geometrico IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // recupero la superficie ISurfBezier* pSurfBez = GetSurfBezier( GetSurf( pGeomDB->GetGeoObj( nSurfId))) ; // recupero le due isocurve const ICurve* pSyncStart = GetCurveLine( GetCurve( pGeomDB->GetGeoObj( nSyncStartId))) ; const ICurve* pSyncEnd = GetCurveLine( GetCurve( pGeomDB->GetGeoObj( nSyncEndId))) ; Point3d ptS1 ; pSyncStart->GetStartPoint( ptS1) ; Point3d ptE1 ; pSyncStart->GetEndPoint( ptE1) ; BIPOINT bpIsoStart( ptS1, ptE1) ; Point3d ptS2 ; pSyncEnd->GetStartPoint( ptS2) ; Point3d ptE2 ; pSyncEnd->GetEndPoint( ptE2) ; BIPOINT bpIsoEnd( ptS2, ptE2) ; PtrOwner pNewSurf( RegolarizeBordersLocally( pSurfBez, bpIsoStart, bpIsoEnd, dLinTol, nType)) ; if ( IsNull( pNewSurf)) return GDB_ID_NULL ; int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pNewSurf)) ; return nId ; }