//---------------------------------------------------------------------------- // 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, bool bMainIsFirstBorder, int nSyncLayerId, int nLineSId, int nLineEId, bool bShorterSide, 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 = 2 ; 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 && bShorterSide) { swap( Line1, Line2) ; swap( pCrvSyncS, pCrvSyncE) ; swap( dThetaStart, dThetaEnd) ; swap( dPhiStart, dPhiEnd) ; } } } // 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) { if ( bMainIsFirstBorder) { // 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)) ; } else { // Se non ho linee di sincronizzazione if ( vSyncPoints.empty()) pSurfBzRuled.Set( GetSurfBezierRuledSmooth( pCrvOtherEdge, pCrvMainEdge, vSyncPoints, ISO_PAR_SAMPLE)) ; // Se ho linee di sincronizzazione else pSurfBzRuled.Set( GetSurfBezierRuledGuided( pCrvOtherEdge, pCrvMainEdge, 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 ( ! bMainIsFirstBorder) swap( LineInterpS.first, 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 ( ! bMainIsFirstBorder) swap( LineInterpE.first, 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 ; }