diff --git a/VolZmap.h b/VolZmap.h index 5f5dfb0..f782695 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -476,13 +476,14 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool CDeSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise = false) const ; // Funzione per crezione solido in parallelo bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, - const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM, INTTOCHECKVEC& vIntToCheck) ; + const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM, bool bForceClosed) ; bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; - bool AdjustDexelThroughCracks( const std::vector& vvIntersToCheck) ; - INTINTVECTOR GetNeighbours( int nG, int nI, int nJ) ; + bool AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHECKVEC& vIntToCheck, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, const IntersParLinesSurfTm& intPLSTM) ; + DBLDBLVECTOR GetNeighbours( int nG, int nI, int nJ, double dPar) ; // Funzioni per Offset di superfici bool InitVolZMapOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ; bool InitVolZMapThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ; diff --git a/VolZmapCreation.cpp b/VolZmapCreation.cpp index bc8e425..5fd0fd2 100644 --- a/VolZmapCreation.cpp +++ b/VolZmapCreation.cpp @@ -543,7 +543,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double //---------------------------------------------------------------------------- bool VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, - const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM, INTTOCHECKVEC& vIntToCheck) + const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM, bool bForceClosed) { if ( nMap < 0 || nMap > 2 || nInfI < 0 || nInfI > m_nNx[nMap] || @@ -554,6 +554,8 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ; + INTTOCHECKVEC vIntToCheck ; + // Determinazione e ridimensionamento dei dexel interni alla trimesh for ( int i = nInfI ; i < nSupI ; ++ i) { for ( int j = nInfJ ; j < nSupJ ; ++ j) { @@ -585,6 +587,14 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co int nInt = int( IntersectionResults.size()) ; + if ( nInt == 1) { + int nT = IntersectionResults[0].nT ; + int nF = Surf.GetFacetFromTria( nT) ; + Vector3d vtN ; Surf.GetFacetNormal( nF, vtN) ; + vIntToCheck.emplace_back( IntersectionResults[0].ptI, vtN, IntersectionResults[0].dU, nMap, i, j) ; + continue ; + } + int nPos = j * m_nNx[nMap] + i ; bool bInside = false ; @@ -663,6 +673,12 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co } } } + + if ( bForceClosed) { + if ( ! AdjustDexelThroughCracks( nMap, vtLen, vIntToCheck, ptMapOrig, Surf, intPLSTM)) + return false ; + } + return true ; } @@ -948,7 +964,6 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex // ciclo sulle griglie bool bCompleted = true ; - vector vvIntersToCheck(3) ; for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) { // Definisco dei sistemi di riferimento ausiliari @@ -980,7 +995,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex nInfI = nSupI ; nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG, - nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM), ref(vvIntersToCheck[nG])) ; + nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM), bForceClosed) ; } } else { @@ -992,7 +1007,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex nInfJ = nSupJ ; nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG, - 0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM), ref(vvIntersToCheck[nG])) ; + 0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM), bForceClosed) ; } } @@ -1011,7 +1026,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex // !!!! NON MULTITHREAD : SOLO PER DEBUG !!!! else { - CreateMapPart( nG, 0, m_nNx[nG], 0, m_nNy[nG], vtLen, ptMapOrig, Surf, intPLSTM, vvIntersToCheck[nG]) ; + CreateMapPart( nG, 0, m_nNx[nG], 0, m_nNy[nG], vtLen, ptMapOrig, Surf, intPLSTM, bForceClosed) ; } } @@ -1027,116 +1042,174 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex // Con espansione non va considerato box (calcolo trimesh va in crash) m_nShape = ( dExtraBox <= EPS_ZERO && IsBox() ? BOX : GENERIC) ; - if ( bForceClosed) { - if ( ! AdjustDexelThroughCracks( vvIntersToCheck)) { - Clear() ; - if ( nError != nullptr) - *nError = 2 ; - return false ; - } - } - // Aggiornamento dello stato m_nStatus = OK ; return bCompleted ; } -INTINTVECTOR -VolZmap::GetNeighbours( int nG, int nI, int nJ) +DBLDBLVECTOR +VolZmap::GetNeighbours( int nG, int nI, int nJ, double dPar) { - INTINTVECTOR vNeigh ; + DBLDBLVECTOR vNeigh ; // parto da in basso a sinistra e procedo per righe, saltando il punto corrente if ( nI > 0 && nJ > 0) - vNeigh.emplace_back( nI - 1, nJ - 1) ; + vNeigh.emplace_back( nI - dPar, nJ - dPar) ; if ( nJ > 0) { - vNeigh.emplace_back( nI, nJ - 1) ; - if ( nI < m_nNx[nG] - 1) - vNeigh.emplace_back( nI + 1, nJ - 1) ; + vNeigh.emplace_back( nI, nJ - dPar) ; + if ( nI < m_nNx[nG] - dPar) + vNeigh.emplace_back( nI + dPar, nJ - dPar) ; } // passo alla fila contenente il punto corrente if ( nI > 0) - vNeigh.emplace_back( nI - 1, nJ) ; - if ( nI < m_nNx[nG] - 1) - vNeigh.emplace_back( nI + 1, nJ) ; + vNeigh.emplace_back( nI - dPar, nJ) ; + if ( nI < m_nNx[nG] - dPar) + vNeigh.emplace_back( nI + dPar, nJ) ; // passo alla fila successiva a quella del corrente - if ( nJ < m_nNy[nG] - 1) { + if ( nJ < m_nNy[nG] - dPar) { if ( nI > 0) - vNeigh.emplace_back( nI - 1, nJ + 1) ; - vNeigh.emplace_back( nI, nJ + 1) ; + vNeigh.emplace_back( nI - dPar, nJ + dPar) ; + vNeigh.emplace_back( nI, nJ + dPar) ; if ( nI < m_nNx[nG]) - vNeigh.emplace_back( nI + 1, nJ + 1) ; + vNeigh.emplace_back( nI + dPar, nJ + dPar) ; } return vNeigh ; } //---------------------------------------------------------------------------- bool -VolZmap::AdjustDexelThroughCracks( const std::vector& vvIntToCheck) +VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHECKVEC& vIntToCheck, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, const IntersParLinesSurfTm& intPLSTM) { + double dAngSameFace = 45 ; + double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ; // per ogni intersezione segnalata devo cercare sugli spilloni vicini l'intervallo con l'estremo più vicino a questa intersezione // e usare l'altro estremo, insieme a quello degli altri spilloni vicini, per estrapolare quello mancante sullo spillone corrente - for ( int nG = 0 ; nG < m_nMapNum ; ++nG) { - Vector3d vtAx ; - if ( nG == 0) - vtAx = Z_AX ; - else if ( nG == 1) - vtAx = X_AX ; - else if ( nG == 2) - vtAx = Y_AX ; - for ( const auto& itc : vvIntToCheck[nG]) { - INTINTVECTOR vNeigh = GetNeighbours( nG, itc.nI, itc.nJ) ; - int nPos = itc.nJ * m_nNx[nG] + itc.nI ; - PNTVECTOR vNeighInters ; - double dPosRef = itc.ptInters.z ; - Vector3d vtMeanN = V_NULL ; - bool bSearchingInOrOut = itc.vtN * vtAx > 0 ; - for ( const auto& [i,j] : vNeigh) { - double dMinDist = INFINITO ; - double dNearestPos = NAN ; - Vector3d vtNearestN ; - int nNeighPos = j * m_nNx[nG] + i ; - for ( const auto& data: m_Values[nG][nNeighPos]) { - double dDist1 = abs( dPosRef - data.dMin) ; - double dDist2 = abs( dPosRef - data.dMax) ; - if ( dDist1 < dMinDist || dDist2 < dMinDist) { - dMinDist = min( dDist1, dDist2) ; + Vector3d vtAx ; + if ( nG == 0) + vtAx = Z_AX ; + else if ( nG == 1) + vtAx = X_AX ; + else if ( nG == 2) + vtAx = Y_AX ; + for ( const auto& itc : vIntToCheck) { + int nPos = itc.nJ * m_nNx[nG] + itc.nI ; + double dPosRef = itc.ptInters.v[( nG + 2) % 3] ; + // controllo se esiste già un intervallo con un estremo quasi coincidente a quello segnalato + // ed entrambi sono entrate o uscite + bool bNeedToReconstruct = true ; + for ( const auto& data: m_Values[nG][nPos]) { + if ( (( abs( dPosRef - data.dMin) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMinN * vtAx) > 0)) || + (( abs( dPosRef - data.dMax) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMaxN * vtAx) > 0))) { + bNeedToReconstruct = false ; + break ; + } + } + if ( ! bNeedToReconstruct) + continue ; + DBLDBLVECTOR vNeigh = GetNeighbours( nG, itc.nI, itc.nJ, m_dStep) ; + PNTVECTOR vNeighInters ; + Vector3d vtMeanN = V_NULL ; + bool bSearchingInOrOut = itc.vtN * vtAx > 0 ; + bool bUseNeighInfo = true ; + for ( const auto& [i,j] : vNeigh) { + double dMinDist = INFINITO ; + double dCorrespInters = INFINITO ; + double dNearestPos = NAN ; + Vector3d vtNearestN ; + int nNeighPos = int( j) * m_nNx[nG] + int( i) ; + for ( const auto& data: m_Values[nG][nNeighPos]) { + double dDist1 = abs( dPosRef - data.dMin) ; + double dDist2 = abs( dPosRef - data.dMax) ; + if ( dDist1 < dMinDist || dDist2 < dMinDist) { + dMinDist = min( dDist1, dDist2) ; - // se sto cercando un ingresso - if ( bSearchingInOrOut) { - if ( data.vtMaxN * vtAx < 0) { - dNearestPos = data.dMax ; - vtNearestN = data.vtMaxN ; - } - else if ( data.vtMinN * vtAx < 0) { - dNearestPos = data.dMin ; - vtNearestN = data.vtMinN ; - } + // se sto cercando un ingresso + if ( bSearchingInOrOut) { + if ( data.vtMaxN * vtAx < 0) { + dNearestPos = data.dMax ; + vtNearestN = data.vtMaxN ; + dCorrespInters = data.dMin ; } - else { - if ( data.vtMaxN * vtAx > 0) { - dNearestPos = data.dMax ; - vtNearestN = data.vtMaxN ; - } - else if ( data.vtMinN * vtAx > 0) { - dNearestPos = data.dMin ; - vtNearestN = data.vtMinN ; - } + else if ( data.vtMinN * vtAx < 0) { + dNearestPos = data.dMin ; + vtNearestN = data.vtMinN ; + dCorrespInters = data.dMax ; + } + } + // se sto cercando un'uscita + else { + if ( data.vtMaxN * vtAx > 0) { + dNearestPos = data.dMax ; + vtNearestN = data.vtMaxN ; + dCorrespInters = data.dMin ; + } + else if ( data.vtMinN * vtAx > 0) { + dNearestPos = data.dMin ; + vtNearestN = data.vtMinN ; + dCorrespInters = data.dMax ; } } } - if ( isfinite( dNearestPos)) { + } + // verifico che il dNearestPos sia effettivamente associato al tratto che sto cercando di ricostruire + // e non ad un altro presente sullo spillone corrente + bool bAddNearest = true ; + for ( const auto& data: m_Values[nG][nPos]) { + double dDist1 = abs( dCorrespInters - data.dMin) ; + double dDist2 = abs( dCorrespInters - data.dMax) ; + if ( dDist1 < dMinDist || dDist2 < dMinDist) { + bAddNearest = false ; + break ; + } + } + + if ( bAddNearest && isfinite( dNearestPos)) { + // controllo anche che i punti non siano troppo lontani tra loro, altrimenti + // il piano calcolato potrebbe essere una media troppo grezza + double dMaxDist = 3 * m_dStep ; + const bool bTooFar = any_of( vNeighInters.begin(), vNeighInters.end(), + [ dNearestPos, dMaxDist]( const Point3d& pt) { + return abs( pt.z - dNearestPos) > dMaxDist ; + }) ; + double dAng ; + if ( ! bTooFar) { + // controllo anche che gli angoli delle normali non cambino troppo + // calcolo l'angolo con la media delle precedenti perché il valore oltre cui + // considero le normali diverse è grande + vtNearestN.GetAngle( vtMeanN, dAng) ; + } + bAddNearest = ! bTooFar && dAng < dAngSameFace ; + if ( bAddNearest) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; vNeighInters.emplace_back( dX, dY, dNearestPos) ; vtMeanN += vtNearestN ; } + else { + bUseNeighInfo = false ; + break ; + } } + } + Point3d ptInt ; + // se riesco uso i vicini per calcolare l'intersezione mancante + if ( bUseNeighInfo) { + // se non ci sono almeno tre punti, non allineati, non riesco a determinare il piano con cui tagliare lo spillone + if ( ssize( vNeighInters) < 3) + continue ; + else if ( ssize( vNeighInters) == 3){ + // verifico che non siano allineati + if ( ( vNeighInters[0].x == vNeighInters[1].x && vNeighInters[0].x == vNeighInters[1].x) || + ( vNeighInters[0].y == vNeighInters[1].y && vNeighInters[0].y == vNeighInters[1].y)) + continue ; + } + // se sono più di tre sicuramente non sono allieanti, visto che sono intorno allo spillone corrente vtMeanN.Normalize() ; Plane3d plLoc ; PolyLine PL ; PL.FromPointVector( vNeighInters) ; PL.IsFlat( plLoc, INFINITO) ; - Point3d ptInt ; + // porto anche il punto dell'intersezione nel frame della griglia Point3d ptKnown = itc.ptInters ; Frame3d frGrid ; @@ -1148,31 +1221,141 @@ VolZmap::AdjustDexelThroughCracks( const std::vector& vvIntToChec frGrid.Set( ORIG, Z_AX, X_AX, Y_AX) ; ptKnown.ToLoc( frGrid) ; IntersLinePlane( ptKnown, Z_AX, INFINITO, plLoc, ptInt, false) ; - - double dMin, dMax ; - Vector3d vtMinN, vtMaxN ; - if ( itc.dU < ptInt.z) { - dMin = itc.dU ; - dMax = ptInt.z ; - vtMinN = itc.vtN ; - vtMaxN = vtMeanN ; - } - else { - dMin = ptInt.z ; - dMax = itc.dU ; - vtMinN = vtMeanN ; - vtMaxN = itc.vtN ; - } - m_Values[nG][nPos].emplace_back() ; - m_Values[nG][nPos].back().dMin = dMin; - m_Values[nG][nPos].back().dMax = dMax ; - m_Values[nG][nPos].back().vtMinN = vtMinN ; - m_Values[nG][nPos].back().vtMaxN = vtMaxN ; - m_Values[nG][nPos].back().nToolMin = 0 ; - m_Values[nG][nPos].back().nToolMax = 0 ; - m_Values[nG][nPos].back().nCompo = 0 ; - std::sort( m_Values[nG][nPos].begin(), m_Values[nG][nPos].end(), []( Data& a, Data& b) { return a.dMin < b.dMin ;}) ; } + // altrimenti sposto di poco lo spillone e ricalcolo le intersezioni con la superficie, finché trovo l'intersezione mancante + else { + bool bFound = false ; + DBLVECTOR vSmallStep ; + vSmallStep.push_back( Clamp( 0.05 * m_dStep, 50 * EPS_SMALL, 1.)) ; + vSmallStep.push_back( Clamp( 0.2 * m_dStep, 50 * EPS_SMALL, 1.)) ; + // ciclo una raggiera di spilloni ( a distanza inferiore allo m_dStep) attorno allo spillone + // appena trova un'intersezione buona mi fermo + // se ciclando la raggiera non trovo un'intersezione valida allora potrei essermi spostato troppo poco dallo spillone originale e essere caduto ancora nella fessura + // quindi ciclo nuovamente aumentando un poco la distanza dallo spillone originale ( comunque sempre meno della distanza m_dStep) + for ( int c = 0 ; c < ssize( vSmallStep) ; ++c) { + DBLDBLVECTOR vSmallMoveNeigh = GetNeighbours( nG, itc.nI, itc.nJ, vSmallStep[c]) ; + for ( int n = 0 ; n < 8 ; ++n) { + double dX = ( vSmallMoveNeigh[n].first + 0.5) * m_dStep ; + double dY = ( vSmallMoveNeigh[n].second + 0.5) * m_dStep ; + Point3d ptP0( dX, dY, 0) ; + ILSIVECTOR IntersectionResults ; + intPLSTM.GetInters( ptP0, vtLen.v[(nG+2)%3], IntersectionResults) ; + // intervalli dalle intersezioni + vector vNewIntervals ; + bool bInside = false ; + Vector3d vtInN ; + Point3d ptIn ; + for ( int i = 0 ; i < ssize( IntersectionResults) ; ++i) { + // Se c'è intersezione + if ( IntersectionResults[i].nILTT != ILTT_NO) { + if ( i > 0) { + int z = i - 1 ; + // controllo se l'intersezione corrente è coincidente con la precedente, per esempio se ILTT == 4 ( intersezione su un lato di un triangolo, quindi con 2 triangoli) + if ( IntersectionResults[i].dU - IntersectionResults[z].dU < EPS_SMALL && + IntersectionResults[i].dCosDN - IntersectionResults[z].dCosDN < EPS_SMALL) + continue ; + } + double dCos = IntersectionResults[i].dCosDN ; + // entro nella superficie trimesh + if ( dCos < - dCosSmall) { + ptIn = IntersectionResults[i].ptI ; + + int nT = IntersectionResults[i].nT ; + int nF = Surf.GetFacetFromTria( nT) ; + + Surf.GetFacetNormal( nF, vtInN) ; + + bInside = true ; + } + + // esco dalla superficie trimesh + else if ( dCos > dCosSmall && bInside) { + Point3d ptOut = IntersectionResults[i].ptI ; + + int nT = IntersectionResults[i].nT ; + int nF = Surf.GetFacetFromTria( nT) ; + + Vector3d vtOutN ; + Surf.GetFacetNormal( nF, vtOutN) ; + + // Aggiungo un tratto al dexel + vNewIntervals.emplace_back() ; + + // Aggiorno dati del tratto di dexel + vNewIntervals.back().dMin = ptIn.v[(nG+2)%3] - ptMapOrig.v[(nG+2)%3] ; + vNewIntervals.back().dMax = ptOut.v[(nG+2)%3] - ptMapOrig.v[(nG+2)%3] ; + vNewIntervals.back().vtMinN = vtInN ; + vNewIntervals.back().vtMaxN = vtOutN ; + vNewIntervals.back().nToolMin = 0 ; + vNewIntervals.back().nToolMax = 0 ; + vNewIntervals.back().nCompo = 0 ; + + bInside = false ; + } + } + } + // controllo che abbia un intervallo in più rispetto a quelli di prima + if ( ssize( vNewIntervals) == ssize( m_Values[nG][nPos]) + 1) { + // dovrei verificare che quello in più sia effettivamente quello ricercato???? + double dMinDist = INFINITO ; + for ( const auto& data : vNewIntervals) { + if ( abs( data.dMin - dPosRef) < dMinDist) { + dMinDist = abs( data.dMin - dPosRef) ; + ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMax) ; + vtMeanN = data.vtMaxN ; + bFound = true ; + } + if ( abs( data.dMax - dPosRef) < dMinDist) { + dMinDist = abs( data.dMax - dPosRef) ; + ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMin) ; + vtMeanN = data.vtMinN ; + bFound = true ; + } + } + } + if ( bFound) + break ; + } + if ( bFound) + break ; + } + // se cercando nei d'intorni dello spillone non ho trovato l'intersezione mancante, mi arrendo + if ( ! bFound) + continue ; + } + + double dMin, dMax ; + Vector3d vtMinN, vtMaxN ; + if ( itc.dU < ptInt.z) { + dMin = itc.dU ; + dMax = ptInt.z ; + vtMinN = itc.vtN ; + vtMaxN = vtMeanN ; + } + else { + dMin = ptInt.z ; + dMax = itc.dU ; + vtMinN = vtMeanN ; + vtMaxN = itc.vtN ; + } + //// prima di aggiungere il tratto verifico che non si sovrapponga con un tratto già presente + //for ( const auto& data: m_Values[nG][nPos]) { + // if ( ( dMin > data.dMin && dMin < data.dMax) || + // ( dMax > data.dMin && dMax < data.dMax) || + // ( dMin < data.dMin && dMax > data.dMax)) + // continue ; + //} + + m_Values[nG][nPos].emplace_back() ; + m_Values[nG][nPos].back().dMin = dMin; + m_Values[nG][nPos].back().dMax = dMax ; + m_Values[nG][nPos].back().vtMinN = vtMinN ; + m_Values[nG][nPos].back().vtMaxN = vtMaxN ; + m_Values[nG][nPos].back().nToolMin = 0 ; + m_Values[nG][nPos].back().nToolMax = 0 ; + m_Values[nG][nPos].back().nCompo = 0 ; + std::sort( m_Values[nG][nPos].begin(), m_Values[nG][nPos].end(), []( Data& a, Data& b) { return a.dMin < b.dMin ;}) ; } + return true ; } \ No newline at end of file