diff --git a/Color.cpp b/Color.cpp index 4a1121a..0d21e19 100644 --- a/Color.cpp +++ b/Color.cpp @@ -127,7 +127,7 @@ GetHSVFromColor( const Color& cCol) hsv.dSat = dDelta / dMax ; if ( cCol.GetRed() >= dMax) // tra giallo e magenta hsv.dHue = ( cCol.GetGreen() - cCol.GetBlue()) / dDelta ; - else if( cCol.GetGreen() >= dMax) // tra ciano e giallo + else if ( cCol.GetGreen() >= dMax) // tra ciano e giallo hsv.dHue = 2.0 + ( cCol.GetBlue() - cCol.GetRed()) / dDelta ; else // tra magenta e ciano hsv.dHue = 4.0 + ( cCol.GetRed() - cCol.GetGreen()) / dDelta ; diff --git a/CurveAux.cpp b/CurveAux.cpp index c4ba761..d75372b 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -687,7 +687,7 @@ EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, d // adatto ogni sottocurva cubica PtrOwner pCCEdited( CreateCurveComposite()) ; for ( int i = 0 ; i < pBezCubics->GetCurveCount() ; ++i) { - if( ! pCCEdited->AddCurve( EditBezierCurve( GetCurveBezier( pBezCubics->GetCurve( i)), nDeg, bMakeRatOrNot, dTol)) ) + if ( ! pCCEdited->AddCurve( EditBezierCurve( GetCurveBezier( pBezCubics->GetCurve( i)), nDeg, bMakeRatOrNot, dTol)) ) return nullptr ; } return Release( pCCEdited) ; @@ -1149,7 +1149,7 @@ FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) else nLow = nMid ; nMid = ( nLow + nHigh) / 2 ; - if( nMid == nDeg - 1) + if ( nMid == nDeg - 1) break ; } nSpan = nMid ; @@ -1174,7 +1174,7 @@ CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTO for ( int r = 0 ; r < j ; ++r) { double dSum = vRight[r+1] + vLeft[j-r] ; double dTemp = 0 ; - if( dSum > EPS_ZERO) + if ( dSum > EPS_ZERO) dTemp = vBasis[r] / dSum ; vBasis[r] = dSaved + vRight[r+1] * dTemp ; dSaved = vLeft[j-r] * dTemp ; @@ -1198,7 +1198,7 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, // se ho solo due punti restituisco una linea CurveLine cl ; cl.Set( vPnt[nStart], vPnt[nEnd]) ; pCrvInt.Set( LineToBezierCurve( &cl, nDeg, false)) ; - if( ! IsNull( pCrvInt) && pCrvInt->IsValid()) + if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) return Release( pCrvInt) ; else return nullptr ; @@ -1206,10 +1206,10 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, else if (nPoints == 3) { // se ho solo tre punti uso un altro algoritmo CurveByInterp cbi ; - for( int i = nStart ; i <= nEnd ; ++i) + for ( int i = nStart ; i <= nEnd ; ++i) cbi.AddPoint( vPnt[i]) ; pCrvInt.Set( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ; - if( ! IsNull( pCrvInt) && pCrvInt->IsValid()) + if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) return Release( pCrvInt) ; else return nullptr ; @@ -1248,7 +1248,7 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ; DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ; CalcBasisFunc( vPntParam[i], nSpan, nDeg, vKnots, vBasis) ; - for( int j = nSpan - nDeg + 1 ; j <= nSpan + 1 ; ++j) + for ( int j = nSpan - nDeg + 1 ; j <= nSpan + 1 ; ++j) mA.row(i).col(j) << vBasis[j - nSpan + nDeg - 1] ; } } @@ -1273,7 +1273,7 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, pCrvInt.Set( NurbsToBezierCurve( cNurbs)) ; - if( ! IsNull(pCrvInt) && pCrvInt->IsValid()) + if ( ! IsNull(pCrvInt) && pCrvInt->IsValid()) return Release( pCrvInt) ; else return nullptr ; @@ -1292,7 +1292,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa // scelgo il parametro associato ad ogni punto in modo che rispecchi la distanza tra i punti double dErr = INFINITO ; int nItCount = 0 ; - while( dErr > dLinTol && nItCount < 10) { + while ( dErr > dLinTol && nItCount < 10) { pCrvInt->Clear() ; int nPoints = int( vPnt.size()) ; int nDeg = 3 ; @@ -1302,7 +1302,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa // se ho solo due punti restituisco una linea CurveLine cl ; cl.Set( vPnt[0], vPnt[1]) ; pCrvInt->AddCurve( LineToBezierCurve( &cl, nDeg, false)) ; - if( ! IsNull( pCrvInt) && pCrvInt->IsValid()) + if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) return Release( pCrvInt) ; else return nullptr ; @@ -1310,10 +1310,10 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa else if ( nPoints == 3) { // se ho solo tre punti uso un altro algoritmo CurveByInterp cbi ; - for( int i = 0 ; i < int( vPnt.size()) ; ++i) + for ( int i = 0 ; i < int( vPnt.size()) ; ++i) cbi.AddPoint( vPnt[i]) ; pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ; - if( ! IsNull( pCrvInt) && pCrvInt->IsValid()) + if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) return Release( pCrvInt) ; else return nullptr ; @@ -1324,14 +1324,14 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa int nStart = 0, nEnd = 0 ; bool bOk = true ; bool bFoundLine = false ; - while( nStart < nPoints - 1 && bOk) { + while ( nStart < nPoints - 1 && bOk) { bFoundLine = false ; nEnd = 0 ; DBLVECTOR vLen ; double dLenTot = 0 ; for ( int i = nStart ; i < nPoints - 1 ; ++i) { double dLen = Dist( vPnt[i], vPnt[i+1]) ; - if( dLen < dMaxLen) { + if ( dLen < dMaxLen) { vLen.push_back( dLen) ; dLenTot += dLen ; } @@ -1342,8 +1342,8 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa } } - if( vLen.size() != 0) { - if( nEnd == 0) + if ( vLen.size() != 0) { + if ( nEnd == 0) nEnd = nPoints - 1 ; pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot)) ; } @@ -1358,13 +1358,13 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa } CalcApproxError( pCrvOri, pCrvInt, dErr) ; - if( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL) + if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL) dMaxLen /= 2 ; ++ nItCount ; } - if( ! IsNull( pCrvInt) && pCrvInt->IsValid() && dErr < dLinTol) + if ( ! IsNull( pCrvInt) && pCrvInt->IsValid() && dErr < dLinTol) return Release( pCrvInt) ; else return nullptr ; @@ -1382,12 +1382,12 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) Point3d pt ; plApprox.GetFirstPoint( pt) ; do { vPnt.push_back( pt) ; - }while( plApprox.GetNextPoint( pt)) ; + } while ( plApprox.GetNextPoint( pt)) ; // campiono punti lungo la curva e poi li interpolo PtrOwner pCC( InterpolatePointSetWithBezier( vPnt, dTol, 100)) ; - if( ! IsNull( pCC) && pCC->IsValid()) + if ( ! IsNull( pCC) && pCC->IsValid()) return Release( pCC) ; else return nullptr ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 77e592a..b22bc43 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -373,7 +373,7 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc) { if ( &cbSrc == this) return true ; - if( ! cbSrc.IsValid()) + if ( ! cbSrc.IsValid()) return false ; if ( ! Init( cbSrc.m_nDeg, cbSrc.m_bRat)) return false ; @@ -1825,19 +1825,19 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) return false ; // se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim Point3d ptStart ; - if( m_bRat) + if ( m_bRat) GetPointD1D2( dUStartTrim, ptStart) ; // trim finale if ( ! TrimEndAtParam( dUEndTrim)) return false ; // trim iniziale con il parametro opportunamente ricalcolato double dNewUStartTrim ; - if( m_bRat) + if ( m_bRat) GetParamAtPoint( ptStart, dNewUStartTrim) ; else dNewUStartTrim = dUStartTrim / dUEndTrim ; //trim iniziale - if( ! TrimStartAtParam( dNewUStartTrim)) + if ( ! TrimStartAtParam( dNewUStartTrim)) return false ; return true ; @@ -1860,7 +1860,7 @@ CurveBezier::TrimStartAtLen( double dLenTrim) return false ; // utilizzo il trim sui parametri - if( ! TrimStartAtParam( dUTrim)) + if ( ! TrimStartAtParam( dUTrim)) return false ; return true ; @@ -1883,7 +1883,7 @@ CurveBezier::TrimEndAtLen( double dLenTrim) return false ; // utilizzo il trim sui parametri - if( ! TrimEndAtParam( dUTrim)) + if ( ! TrimEndAtParam( dUTrim)) return false ; return true ; @@ -2377,10 +2377,10 @@ CurveBezier::MakeNonRational( double dTol) Point3d ptCen = iccInfo.IciA[0].ptI ; // se sia l'inizio che la fine della curva distano uguale dal punto di intersezione tra i due assi trovati allora la curva è un arco di circonferenza - if( abs(Dist( pt0, ptCen) - Dist( pt3, ptCen)) < EPS_SMALL) { + if ( abs(Dist( pt0, ptCen) - Dist( pt3, ptCen)) < EPS_SMALL) { PtrOwner pNew ( ApproxArcCurveBezierWithSingleCubic( this, ptCen, vtN)) ; - if( IsNull( pNew) || ! pNew->IsValid()) + if ( IsNull( pNew) || ! pNew->IsValid()) return false ; Init( 3, false) ; for ( int i = 0 ; i < 3 ; ++i) @@ -2412,7 +2412,7 @@ CurveBezier::MakeNonRational( double dTol) Point3d pt ; pNewBez->GetPointD1D2( double( p) / nDeg, pt) ; Vector3d vDiff = vPntSampling[p] - pt ; double dErrLoc = vDiff.Len() ; - if( dErrLoc > dErrMax) + if ( dErrLoc > dErrMax) dErrMax = dErrLoc ; // aggiorno il vettore dei punti di controllo della nuova curva vPntCtrl[p] += vDiff ; @@ -2456,7 +2456,7 @@ CurveBezier::IsALine( void) const Point3d ptCtrl = GetControlPoint( i) ; DistPointLine dpl( ptCtrl, ptStart, ptEnd) ; double dDist = 0 ; dpl.GetDist( dDist) ; - if( dDist > EPS_SMALL) + if ( dDist > EPS_SMALL) return false ; } return true ; diff --git a/DistPointSurfBz.cpp b/DistPointSurfBz.cpp index 0495786..81f6f17 100644 --- a/DistPointSurfBz.cpp +++ b/DistPointSurfBz.cpp @@ -55,7 +55,7 @@ DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz) //salvo il punto corrispondente nel parametrico srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ; // salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto - srfBz.GetPointNrmD1D2( m_ptParam.x / SBZ_TREG_COEFF, m_ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ; + srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ; // salvo la distanza minima m_dDist = Dist( ptP, m_ptMinDistPoint) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 870da00..04141b8 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/GeomDB.cpp b/GeomDB.cpp index fd300d2..964cf4b 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -38,16 +38,18 @@ using namespace std ; class LockAddErase { public : - LockAddErase( atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) + LockAddErase( atomic_flag& bAddEraseOn, bool bUse = true) + : m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) { if ( ! m_bUse) return ; - while ( m_bAddEraseOn.test_and_set()) { - this_thread::sleep_for( chrono::nanoseconds{ 1}) ; + while ( m_bAddEraseOn.test_and_set( memory_order_acquire)) { + m_bAddEraseOn.wait( true, memory_order_relaxed) ; } } ; ~LockAddErase( void) { if ( ! m_bUse) return ; - m_bAddEraseOn.clear() ; + m_bAddEraseOn.clear( memory_order_release) ; + m_bAddEraseOn.notify_one() ; } ; private : diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index 99e3431..0b88c9e 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -291,6 +291,24 @@ IntersCurveCurve::GetIntersCount( void) return m_nIntersCount ; } +//---------------------------------------------------------------------------- +int +IntersCurveCurve::GetInters3DCount( void) +{ + int nCount = 0 ; + for( int i = 0 ; i < m_nIntersCount ; ++i) { + if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { + if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL) + ++nCount ; + } + else { + if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL) + ++nCount ; + } + } + return nCount ; +} + //---------------------------------------------------------------------------- int IntersCurveCurve::GetCrossIntersCount( void) @@ -340,6 +358,30 @@ IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) return true ; } +//---------------------------------------------------------------------------- +bool +IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) +{ + if ( nInd < 0 || nInd >= GetInters3DCount()) + return false ; + int nCount = - 1 ; + for( int i = 0 ; i < m_nIntersCount ; ++i) { + if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { + if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL) + ++nCount ; + } + else { + if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL) + ++nCount ; + } + if( nCount == nInd) { + aInfo = m_Info[nInd] ; + return true ; + } + } + return false ; +} + //---------------------------------------------------------------------------- bool IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d& ptI) diff --git a/IntersCurvePlane.cpp b/IntersCurvePlane.cpp index 756c753..8ca95fb 100644 --- a/IntersCurvePlane.cpp +++ b/IntersCurvePlane.cpp @@ -63,11 +63,11 @@ IntersCurvePlane::IntersCurvePlane( const ICurve& Curve, const Point3d& ptOrig, pCalcCrv = m_pCurve ; m_Info.clear() ; - if( pCalcCrv->GetType() == CRV_LINE) { + if ( pCalcCrv->GetType() == CRV_LINE) { CalcIntersLinePlane( m_plPlane, *pCalcCrv) ; } - else if( pCalcCrv->GetType() == CRV_COMPO){ - for( int i = 0 ; i < GetBasicCurveComposite( pCalcCrv)->GetCurveCount(); ++i) { + else if ( pCalcCrv->GetType() == CRV_COMPO){ + for ( int i = 0 ; i < GetBasicCurveComposite( pCalcCrv)->GetCurveCount(); ++i) { const ICurve& subCurve = *GetBasicCurveComposite( pCalcCrv)->GetCurve( i) ; CalcIntersLinePlane( m_plPlane, subCurve, i) ; } @@ -82,7 +82,7 @@ IntersCurvePlane::IntersCurvePlane( const ICurve& Curve, const Point3d& ptOrig, bool IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Curve, int nCrv) { - if( Curve.GetType() != CRV_LINE) + if ( Curve.GetType() != CRV_LINE) return false ; Point3d ptStart ; Curve.GetStartPoint( ptStart) ; Point3d ptEnd ; Curve.GetEndPoint( ptEnd) ; @@ -90,7 +90,7 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur double dLen = 0 ; Curve.GetLength( dLen) ; int nIntersType = IntersLinePlane( ptStart, ptEnd, m_plPlane, ptInt, true) ; // intersezione con attraversamento - if( nIntersType == ILPT_YES) { + if ( nIntersType == ILPT_YES) { IntCrvPlnInfo icpi ; icpi.Ici[0].ptI = ptInt ; icpi.Ici[0].dU = Dist( ptInt, ptStart) / dLen + nCrv ; @@ -100,17 +100,17 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur m_Info.push_back( icpi) ; } // intersezione con tocco - else if( nIntersType == ILPT_START || nIntersType == ILPT_END) { + else if ( nIntersType == ILPT_START || nIntersType == ILPT_END) { IntCrvPlnInfo icpi ; icpi.Ici[0].ptI = ptInt ; icpi.Ici[0].dU = nIntersType == ILPT_START ? 0 : 1 + nCrv ; - if( nIntersType == ILPT_START) { + if ( nIntersType == ILPT_START) { Vector3d vtPos = ptEnd - m_plPlane.GetPoint() ; icpi.Ici[0].nNextTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ; icpi.Ici[0].nPrevTy = ICPT_NULL ; } - else{ + else { Vector3d vtPos = ptStart - m_plPlane.GetPoint() ; icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ; icpi.Ici[0].nNextTy = ICPT_NULL ; @@ -118,7 +118,7 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur m_Info.push_back( icpi) ; } // intersezione con sovrapposizione - else if( nIntersType == ILPT_INPLANE) { + else if ( nIntersType == ILPT_INPLANE) { IntCrvPlnInfo icpi ; icpi.bOverlap = true ; icpi.Ici[0].ptI = ptStart ; @@ -139,22 +139,22 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur void IntersCurvePlane::OrderAndCompleteIntersections() { - if( m_Info.size() < 2) + if ( m_Info.size() < 2) return ; // cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione // riempio le info PrevTy e NexyTy sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ; - for( int curr = m_Info.size() - 1 ; curr > - 1 ; --curr) { + for ( int curr = m_Info.size() - 1 ; curr > - 1 ; --curr) { int prev = curr == 0 ? m_Info.size() - 1 : curr - 1 ; int next = curr == m_Info.size() - 1 ? 0 : curr + 1 ; bool bErasedCurr = false ; // solo le intersezioni di sovrapposizione o puntuali sullo start o end delle curve possono avere il PrevTy o NextTy non definito - if( ! m_Info[curr].bOverlap) { + if ( ! m_Info[curr].bOverlap) { if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) { - if( ! m_Info[prev].bOverlap) { + if ( ! m_Info[prev].bOverlap) { m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ; // se ho due puntuali che coincidono cancello il successivo tra i due ( corrente) - if( AreSamePointApprox( m_Info[curr].Ici[0].ptI, m_Info[prev].Ici[0].ptI)) { + if ( AreSamePointApprox( m_Info[curr].Ici[0].ptI, m_Info[prev].Ici[0].ptI)) { m_Info.erase(m_Info.begin() + curr) ; bErasedCurr = true ; } @@ -167,7 +167,7 @@ IntersCurvePlane::OrderAndCompleteIntersections() } } if ( ! bErasedCurr && m_Info[curr].Ici[0].nNextTy == ICPT_NULL){ - if( ! m_Info[prev].bOverlap) + if ( ! m_Info[prev].bOverlap) m_Info[curr].Ici[0].nNextTy = m_Info[next].Ici[0].nPrevTy ; // se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello else { @@ -178,13 +178,13 @@ IntersCurvePlane::OrderAndCompleteIntersections() } else { if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) { - if( ! m_Info[prev].bOverlap) + if ( ! m_Info[prev].bOverlap) m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ; else m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[1].nNextTy ; } if ( m_Info[curr].Ici[1].nNextTy == ICPT_NULL) { - if( ! m_Info[next].bOverlap) + if ( ! m_Info[next].bOverlap) m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[0].nPrevTy ; else m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[1].nPrevTy ; @@ -194,7 +194,6 @@ IntersCurvePlane::OrderAndCompleteIntersections() m_nIntersCount = m_Info.size() ; } - //---------------------------------------------------------------------------- bool IntersCurvePlane::IsArcToApprox( const ICurve& Curve) diff --git a/IntersLineBox.cpp b/IntersLineBox.cpp index 552f9a6..97868d6 100644 --- a/IntersLineBox.cpp +++ b/IntersLineBox.cpp @@ -113,7 +113,7 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3 double dU1, dU2 ; bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ; - // Se non c'è intersezione + // Se non c'è intersezione if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL))) return true ; @@ -144,8 +144,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3 else if ( dU2 < EPS_SMALL) vInters.emplace_back( ILBT_OUT, 0) ; else { - vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ; - vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ; + if ( dU1 < - EPS_SMALL) + vInters.emplace_back( ILBT_TG_INSIDE, 0.) ; + else + vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ; + if ( dU2 > dLen + EPS_SMALL) + vInters.emplace_back( ILBT_TG_INSIDE, dLen) ; + else + vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ; } } return true ; @@ -162,8 +168,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3 else if ( dU2 < EPS_SMALL) vInters.emplace_back( ILBT_OUT, 0) ; else { - vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ; - vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ; + if ( dU1 < - EPS_SMALL) + vInters.emplace_back( ILBT_INSIDE, 0.) ; + else + vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ; + if ( dU2 > dLen + EPS_SMALL) + vInters.emplace_back( ILBT_INSIDE, dLen) ; + else + vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ; } } return true ; diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index 346613e..7daf922 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -34,7 +34,6 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) { // la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz - pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ; double dDistNew = 0, dDistPre = 0 ; @@ -48,18 +47,18 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b while ( dDistNew > EPS_SMALL && nCount < 100) { dDistPre = dDistNew ; Point3d ptIBzNew1 ; - pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + pSurfBz->GetPointD1D2( ( ptSP.x + dh), ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ; dplNewU.GetDist( dDistNew) ; double dfdU = ( dDistNew - dDistPre) / dh ; Point3d ptIBzNew2 ; - pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + pSurfBz->GetPointD1D2( ptSP.x, ( ptSP.y + dh), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ; dplNewV.GetDist( dDistNew) ; double dfdV = ( dDistNew - dDistPre) / dh ; // mi avvicino cercando di annullare la distanza in un colpo solo double dr = - dDistPre / ( dfdU + dfdV) ; - pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; + pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU), ( ptSP.y + dr * dfdV), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ; dplNew.GetDist( dDistNew) ; ++ nCount ; @@ -143,12 +142,12 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS pSurfTm->GetTriangle( InfoTm.nT, nVert) ; double dU0, dV0 ; pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; - ptSP = ptSP + Point3d(dU0, dV0, 0) ; + ptSP = ptSP + Point3d( dU0, dV0, 0) ; if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) return false ; } Vector3d vtN ; - pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ; + pSurfBz->GetPointNrmD1D2(ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ; double dCos = vtN * vtL ; double dCos2 = 0 ; // eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione) @@ -163,7 +162,7 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) return false ; } - pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ; + pSurfBz->GetPointNrmD1D2( ptSP2.x, ptSP2.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ; dCos2 = vtN * vtL ; } UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ; @@ -251,13 +250,13 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ; // funzione pensata per funzionare solo con una monopatch bilineare - if( nDegU > 1 || nDegV > 1 || nSpanU > 1 || nSpanV > 1 || bRat) + if ( nDegU > 1 || nDegV > 1 || nSpanU > 1 || nSpanV > 1 || bRat) return false ; int nInters = int( vInfo.size()) ; PNTVECTOR vPntCtrl ; - for( int p = 0 ; p < 4 ; ++p) { + for ( int p = 0 ; p < 4 ; ++p) { bool bOk = false ; vPntCtrl.push_back( pSurfBz->GetControlPoint( p, &bOk)) ; } @@ -281,14 +280,14 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, vdCoeff = { (B2 * D1 - B1 * D2), ( A2 * D1 - A1 * D2 + B2 * C1 - B1 * C2), ( A2 * C1 - A1 * C2)} ; int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ; bool bFound = false ; - for( int w = 0 ; w < nRoots ; ++w) { + for ( int w = 0 ; w < nRoots ; ++w) { if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO ) { double dU = 0, dV = vdRoots[w] ; // verifico che non sia una soluzione con molteplicità > 1 bool bAlreadyFound = false ; for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k) bAlreadyFound = abs( dV - vdRoots[k]) < EPS_PARAM ; - if( ! bAlreadyFound) { + if ( ! bAlreadyFound) { dU = (dV * (C1 - C2) + ( D1 - D2)) / ( dV * ( A2 - A1) + ( B2 - B1)) ; if ( dU > - EPS_ZERO && dU < 1 + EPS_ZERO) { Point3d ptIBez, ptIBez2 ; @@ -305,14 +304,14 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, // se tutti i coefficienti sono zero allora potrei avere una linea che giace sulla superficie // per trovare i punti di inizio e fine sovrapposizione trovo i punti a minima distanza tra la linea e gli edge della superficie - if( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) { + if ( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) { ICRVCOMPOPOVECTOR vCrvEdge( 4) ; vCrvEdge[0].Set(pSurfBz->GetCurveOnU( 0)) ; vCrvEdge[1].Set(pSurfBz->GetCurveOnV( 1)) ; vCrvEdge[2].Set(pSurfBz->GetCurveOnU( 1)) ; vCrvEdge[3].Set(pSurfBz->GetCurveOnV( 0)) ; double dAngTolDeg = 5 ; - for( int i = 0 ; i < 4 ; ++i) { + for ( int i = 0 ; i < 4 ; ++i) { PolyLine plApprox ; vCrvEdge[0]->ApproxWithLines( EPS_SMALL, dAngTolDeg, ICurve::ApprLineType::APL_STD, plApprox) ; //CurveComposite cCC ; //cCC.FromPolyLine( plApprox) ; @@ -322,7 +321,7 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, Point3d ptClosest ; int c = 0 ; int nTot = plApprox.GetPointNbr() ; - for( int j = 0 ; j < nTot ; ++j) { + for ( int j = 0 ; j < nTot ; ++j) { DistPointLine dpl( pt, ptL, vtL, dLen, bFinite) ; double dDist = INFINITO ; dpl.GetDist( dDist) ; @@ -339,7 +338,7 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, // tra i due tratti dell'approssimazione che arrivano al punto selezionato come più vicino, devo trovare quale si avvicina di più Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ; Point3d ptEnd ; - for( int z = 1 ; z < nClosestLine - 1 ; ++z) + for ( int z = 1 ; z < nClosestLine - 1 ; ++z) plApprox.GetNextPoint( ptStart) ; plApprox.GetNextPoint( ptEnd) ; // linea precedente al punto @@ -357,12 +356,12 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, double dDistCurr = INFINITO ; dllCurr.GetDist( dDistCurr) ; - if( dDistPre < dDistCurr) + if ( dDistPre < dDistCurr) dllPre.GetMinDistPoints( ptInt1, ptInt2) ; else dllCurr.GetMinDistPoints( ptInt1, ptInt2) ; } - else if ( nClosestLine == 0){ + else if ( nClosestLine == 0) { // il punto più vicino è sulla prima linea Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ; Point3d ptEnd ; plApprox.GetNextPoint( ptEnd) ; @@ -375,7 +374,7 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, // il punto più vicino è sull'ultima linea Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ; Point3d ptEnd ; - for( int z = 1 ; z < nClosestLine - 1 ; ++z) + for ( int z = 1 ; z < nClosestLine - 1 ; ++z) plApprox.GetNextPoint( ptStart) ; plApprox.GetNextPoint( ptEnd) ; Vector3d vtLinePre = ptEnd - ptStart ; @@ -386,23 +385,23 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, double dU1 = 0, dV1 = 0, dU2 = 0, dV2 = 0 ; // se ho trovato due punti vuol dire che la linea coincide con un edge e ho trovato tutto quello che serve - if( ! AreSamePointExact( ptInt2, ORIG)) { - if( i == 0) { + if ( ! AreSamePointExact( ptInt2, ORIG)) { + if ( i == 0) { //dV1 = 0 ; dV2 = 0 ; vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ; vCrvEdge[0]->GetParamAtPoint( ptInt2, dU2) ; } - else if( i == 1) { + else if ( i == 1) { //dU1 = 1 ; dU2 = 1 ; vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ; vCrvEdge[1]->GetParamAtPoint( ptInt2, dV2) ; } - else if( i == 2){ + else if ( i == 2){ //dV1 = 1 ; dV2 = 1 ; vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ; vCrvEdge[2]->GetParamAtPoint( ptInt2, dU2) ; } - else if( i == 3){ + else if ( i == 3){ //dU1 = 0 ; dU2 = 0 ; vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ; vCrvEdge[3]->GetParamAtPoint( ptInt2, dV2) ; @@ -417,11 +416,11 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, double dCos2 = vtN2 * vtL ; // se avevo già trovato un punto singolo che coincide col primo punto di questa intersezione sovrapposta, allora cancello l'intersezione singola che // avevo salvato e aggiungo quella sovrapposto che ho trovato ora - if( bFound) { + if ( bFound) { int nNewTot = int(vInfo.size()) ; int nNewInters = nNewTot - nInters ; bool bAlreadyFound = false ; - for( int i = 0 ; i < nNewInters ; ++i) { + for ( int i = 0 ; i < nNewInters ; ++i) { bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) || AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP2) ; if ( bAlreadyFound) { vInfo.erase( vInfo.begin() + nNewTot - i) ; @@ -434,32 +433,32 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, break ; } // se ho trovato un punto a distanza zero dalla linea allora ho trovato l'intersezione - else if( dMinDist < EPS_SMALL) { - if( i == 0) { + else if ( dMinDist < EPS_SMALL) { + if ( i == 0) { //dV1 = 0 ; vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ; } - else if( i == 1) { + else if ( i == 1) { //dU1 = 1 ; vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ; } - else if( i == 2){ + else if ( i == 2) { //dV1 = 1 ; vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ; } - else if( i == 3){ + else if ( i == 3) { //dU1 = 0 ; vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ; } Point3d ptSP1( dU1, dV1, 0), ptSP2 ; // se avevo trovato già altri punti controllo di non essere esattamente su una diagonale ( e quindi avere un'intersezione con ogni edge, ma due sono doppie) - if( bFound) { + if ( bFound) { int nNewTot = int(vInfo.size()) ; int nNewInters = nNewTot - nInters ; bool bAlreadyFound = false ; - for( int i = 0 ; i < nNewInters ; ++i) + for ( int i = 0 ; i < nNewInters ; ++i) bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) ; - if( bAlreadyFound) + if ( bAlreadyFound) continue ; } @@ -474,16 +473,16 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, } // se la superficie è trimmed verifico che i punti trovati siano all'interno del parametrico trimmato - if( bTrimmed && bFound) { + if ( bTrimmed && bFound) { int nNewTot = int(vInfo.size()) ; int nNewInters = nNewTot - nInters ; const ISurfFlatRegion* pFRTrim = pSurfBz->GetTrimRegion() ; - for( int i = 0 ; i < nNewInters ; ++i) { + for ( int i = 0 ; i < nNewInters ; ++i) { Point3d ptTest = vInfo[nNewTot - i].ptUV * SBZ_TREG_COEFF ; bool bInside = false ; double dDist = INFINITO ; IsPointInsideSurfFr( ptTest, pFRTrim, dDist, bInside) ; - if( ! bInside) + if ( ! bInside) vInfo.erase( vInfo.begin() + nNewTot - i) ; } } diff --git a/IntersLineSurfStd.cpp b/IntersLineSurfStd.cpp index 8123316..3fab574 100644 --- a/IntersLineSurfStd.cpp +++ b/IntersLineSurfStd.cpp @@ -1662,7 +1662,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine, // Riordino le soluzioni for ( int ni = 0 ; ni < int( vdPar.size()) - 1 ; ++ ni) { for ( int nj = ni ; nj < int( vdPar.size()) ; ++ nj) { - if( vdPar[ni] > vdPar[nj]) { + if ( vdPar[ni] > vdPar[nj]) { swap( vdPar[ni], vdPar[nj]) ; } } diff --git a/IntersPlaneVolZmap.cpp b/IntersPlaneVolZmap.cpp index 9f6e0a2..ad99de2 100644 --- a/IntersPlaneVolZmap.cpp +++ b/IntersPlaneVolZmap.cpp @@ -19,7 +19,7 @@ using namespace std ; //---------------------------------------------------------------------------- -// Intersezione di unpiano con la superficie di un solido VolZmap +// Intersezione di un piano con la superficie di un solido VolZmap //---------------------------------------------------------------------------- bool IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop) @@ -28,9 +28,6 @@ IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ; if ( pVzm == nullptr) return false ; - // verifico parametro di ritorno - if ( &vpLoop == nullptr) - return false ; // eseguo intersezione return pVzm->GetPlaneIntersection( plPlane, vpLoop) ; diff --git a/PolyLine.cpp b/PolyLine.cpp index 19a8027..f52f459 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -1974,7 +1974,7 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType, for ( int z = int( vbRep2.size()) - 1 ; z >= nCrv2 ; --z) vbRep2[z] = true ; } - if( nCrv1 < nPnt1) { + if ( nCrv1 < nPnt1) { nRep1 += nPnt1 - nCrv1 ; for ( int z = int( vbRep1.size()) - 1 ; z >= nCrv1 ; --z) vbRep1[z] = true ; diff --git a/ProjectCurveSurf.cpp b/ProjectCurveSurf.cpp index 1c1dd66..e845fb8 100644 --- a/ProjectCurveSurf.cpp +++ b/ProjectCurveSurf.cpp @@ -59,6 +59,77 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, return true ; } +//---------------------------------------------------------------------------- +static bool +AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) +{ + for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { + // precedente + int j = i - 1 ; + // se normali tra corrente e precedente oltre limite e punti abbastanza lontani + if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER && + SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) { + // intersezione tra le due facce + Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ; + Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ; + Point3d ptEdge ; Vector3d vtEdge ; + if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) { + Plane3d plPlane3 ; plPlane3.Set(vPt5ax[i].ptP, (vPt5ax[i].ptP - vPt5ax[j].ptP) ^ ( vPt5ax[i].vtDir1 + vPt5ax[j].vtDir1)) ; + Point3d ptInt ; + if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { + // verifico se spigolo convesso o concavo + bool bConvex ; + if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP)) + bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ; + else + bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ; + // se convesso, metto due punti con direzione appena prima e appena dopo + if ( bConvex) { + Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; + Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; + if ( dLen1 > 2 * EPS_SMALL) { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ; + Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; + Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CVEX ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + else + vPt5ax[j].nFlag = P5AX_CVEX ; + if ( dLen2 > 2 * EPS_SMALL) { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; + Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; + Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CVEX ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + else + vPt5ax[i].nFlag = P5AX_CVEX ; + } + // altrimenti concavo, aggiungo un solo punto con la direzione media + else { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt ; + Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ; + Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CONC ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + } + } + } + } + return true ; +} + //---------------------------------------------------------------------------- static bool RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir) @@ -70,7 +141,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ; // Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo int nInd = 0 ; - while ( nInd < int( vPt5ax.size())) { + while ( nInd < ssize( vPt5ax)) { if ( vPt5ax[nInd].nFlag == P5AX_CONC) { // analizzo i punti appena precedenti int nIpv = nInd - 1 ; @@ -86,7 +157,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, } // analizzo i punti appena successivi int nInx = nInd + 1 ; - while ( nInx < int( vPt5ax.size())) { + while ( nInx < ssize( vPt5ax)) { double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ; if ( dSqLen < dSqMaxLen) vPt5ax[nInx].nFlag = P5AX_TO_DELETE ; @@ -104,7 +175,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, int nPrec = 0 ; int nCurr = 1 ; int nNext = 2 ; - while ( nNext < int( vPt5ax.size())) { + while ( nNext < ssize( vPt5ax)) { bool bRemove = false ; // lunghezza del segmento che unisce gli adiacenti double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ; @@ -161,6 +232,121 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, return true ; } +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax) +{ + // punto sulle supefici a minima distanza + int nSurfMin = -1 ; + int nTriaMin ; + Point3d ptMin ; + double dMinDist ; + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { + // punto sulla superficie a minima distanza + DistPointSurfTm dPS( ptP, *vpStm[i]) ; + double dDist ; + if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) { + nSurfMin = i ; + dPS.GetMinDistPoint( ptMin) ; + dPS.GetMinDistTriaIndex ( nTriaMin) ; + dMinDist = dDist ; + } + } + + // se trovato + if ( nSurfMin >= 0) { + // assegno il punto + Point3d ptInt = ptMin ; + // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) + Triangle3dEx trTria ; + if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria)) + return false ; + Vector3d vtN ; + if ( ! CalcNormal( ptMin, trTria, vtN)) + vtN = trTria.GetN() ; + // assegno valori al punto 5assi + Pt5ax.ptP = ptInt ; + Pt5ax.vtDir1 = vtN ; + Pt5ax.vtDir2 = vtN ; + Pt5ax.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + // ritorno con successo + return true ; + } + + return false ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) +{ + // sistemazioni per tipo di superficie + CISRFTMPVECTOR vpSurfTm ; + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { + const SurfTriMesh* pSurfTm = nullptr ; + switch ( vpSurf[i]->GetType()) { + case SRF_TRIMESH : + pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ; + break ; + case SRF_BEZIER : + { double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ; + SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ; + pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ; + SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ; + } break ; + case SRF_FLATRGN : + pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ; + break ; + default : + break ; + } + if ( pSurfTm == nullptr) + return false ; + vpSurfTm.emplace_back( pSurfTm) ; + } + + // controllo le tolleranze + dLinTol = max( dLinTol, LIN_TOL_MIN) ; + dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; + + // approssimo la curva con una polilinea entro la metà della tolleranza + PolyLine PL ; + if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) + return false ; + const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ; + if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) + return false ; + + // Pulisco e riservo spazio nel vettore dei punti risultanti + vPt5ax.clear() ; + vPt5ax.reserve( PL.GetPointNbr()) ; + + // proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza + double dPar ; + Point3d ptP ; + bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ; + while ( bFound) { + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax)) + vPt5ax.emplace_back( Pt5ax) ; + // passo al successivo + bFound = PL.GetNextUPoint( &dPar, &ptP) ; + } + + // se richiesto, inserimento punti intermedi in presenza di spigoli + if ( bSharpEdges) + AddPointsOnCorners( vPt5ax) ; + + // rimozione punti in eccesso rispetto alle tolleranze + RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; + + return true ; +} + +//---------------------------------------------------------------------------- // --- vettore di oggetti intersezione massiva rette parallele SurfTM -------- typedef std::vector INTPARLINESTMPVECTOR ; @@ -173,11 +359,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame Point3d ptL = GetToLoc( ptP, frRefLine) ; int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) { ILSIVECTOR vIntRes ; if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -231,7 +417,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect { // sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -270,10 +456,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect if ( ! frRefLine.Set( ORIG, vtDir)) return false ; INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ; - for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) { IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ; if ( pIntPLSTM == nullptr) { - for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j) + for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j) delete vpIntPLSTM[j] ; return false ; } @@ -298,72 +484,12 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect } // Libero oggetti per calcolo massivo - for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) + for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) delete vpIntPLSTM[i] ; // se richiesto, inserimento punti intermedi in presenza di spigoli - if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { - // precedente - int j = i - 1 ; - // se normali tra corrente e precedente oltre limite e punti abbastanza lontani - if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER && - SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) { - // intersezione tra le due facce - Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ; - Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ; - Point3d ptEdge ; Vector3d vtEdge ; - if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) { - Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, ( vPt5ax[i].ptP - vPt5ax[j].ptP) ^ vtDir) ; - Point3d ptInt ; - if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { - // verifico se spigolo convesso o concavo - bool bConvex ; - if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP)) - bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ; - else - bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ; - // se convesso, metto due punti con direzione appena prima e appena dopo - if ( bConvex) { - Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; - Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; - if ( dLen1 > 2 * EPS_SMALL) { - Point5ax Pt5ax ; - Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ; - Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; - Pt5ax.vtDir2 = vtDir ; - Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - Pt5ax.nFlag = P5AX_CVEX ; - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - ++ i ; - } - if ( dLen2 > 2 * EPS_SMALL) { - Point5ax Pt5ax ; - Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; - Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; - Pt5ax.vtDir2 = vtDir ; - Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - Pt5ax.nFlag = P5AX_CVEX ; - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - ++ i ; - } - } - // altrimenti concavo, aggiungo un solo punto con la direzione media - else { - Point5ax Pt5ax ; - Pt5ax.ptP = ptInt ; - Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; - Pt5ax.vtDir2 = vtDir ; - Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - Pt5ax.nFlag = P5AX_CONC ; - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - ++ i ; - } - } - } - } - } - } + if ( bSharpEdges) + AddPointsOnCorners( vPt5ax) ; // rimozione punti in eccesso rispetto alle tolleranze RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; @@ -385,11 +511,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP // conservo l'intersezione più alta int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { ILSIVECTOR vIntRes ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -444,7 +570,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo { // sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -497,25 +623,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo } // se richiesto, inserimento punti intermedi in presenza di spigoli - if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { - // precedente - int j = i - 1 ; - // se normali tra corrente e precedente oltre limite e punti abbastanza lontani - if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER && - SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) { - // punto medio - Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ; - double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - // se trovo proiezione, la salvo - Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptMid, vpSurfTm, gpRef, dMid, Pt5ax)) { - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - -- i ; - } - } - } - } + if ( bSharpEdges) + AddPointsOnCorners( vPt5ax) ; // rimozione punti in eccesso rispetto alle tolleranze RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; @@ -540,11 +649,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv // conservo l'intersezione più alta int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { ILSIVECTOR vIntRes ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -600,7 +709,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur { // Sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -653,68 +762,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur } // se richiesto, inserimento punti intermedi in presenza di spigoli - if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { - // precedente - int j = i - 1 ; - // se normali tra corrente e precedente oltre limite e punti abbastanza lontani - if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER && - SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) { - // intersezione tra le due facce - Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ; - Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ; - Point3d ptEdge ; Vector3d vtEdge ; - if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) { - Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir2 ^ vPt5ax[j].vtDir2) ; - Point3d ptInt ; - if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { - // verifico se spigolo convesso o concavo - bool bConvex ; - if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP)) - bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ; - else - bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ; - // se convesso, metto due punti con direzione appena prima e appena dopo - if ( bConvex) { - Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; - Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; - if ( dLen1 > 2 * EPS_SMALL) { - Point5ax Pt5ax ; - Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ; - Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; - Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; - Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - Pt5ax.nFlag = P5AX_CVEX ; - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - ++ i ; - } - if ( dLen2 > 2 * EPS_SMALL) { - Point5ax Pt5ax ; - Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; - Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; - Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; - Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - Pt5ax.nFlag = P5AX_CVEX ; - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - ++ i ; - } - } - // altrimenti concavo, aggiungo un solo punto con la direzione media - else { - Point5ax Pt5ax ; - Pt5ax.ptP = ptInt ; - Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; - Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; - Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - Pt5ax.nFlag = P5AX_CONC ; - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - ++ i ; - } - } - } - } - } - } + if ( bSharpEdges) + AddPointsOnCorners( vPt5ax) ; // rimozione punti in eccesso rispetto alle tolleranze RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; @@ -748,11 +797,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT // intersezione della retta con le superfici (conservo l'intersezione più alta) int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { ILSIVECTOR vIntRes ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -814,7 +863,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur { // sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -888,25 +937,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur } // se richiesto, inserimento punti intermedi in presenza di spigoli - if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { - // precedente - int j = i - 1 ; - // se normali tra corrente e precedente oltre limite e punti abbastanza lontani - if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER && - SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) { - // punto medio - Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ; - double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; - // se trovo proiezione, la salvo - Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptMid, vpSurfTm, *pRefTm, dMid, Pt5ax)) { - vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; - -- i ; - } - } - } - } + if ( bSharpEdges) + AddPointsOnCorners( vPt5ax) ; // rimozione punti in eccesso rispetto alle tolleranze RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index 163eec3..da24792 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -78,7 +78,7 @@ GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) { for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){ vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ; - if( vbInvert[vnPLIndMat[i][j]]) + if ( vbInvert[vnPLIndMat[i][j]]) vPLOrd.back().Invert() ; } } @@ -221,7 +221,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect const ICurveComposite* pCC = GetCurveComposite( pGuide) ; for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; - if( pCrv->GetType() != CRV_LINE) { + if ( pCrv->GetType() != CRV_LINE) { if ( pCrv->GetType() == CRV_BEZIER) { const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ; bGuideIsPolyLine = pCrvBez->IsALine() ; @@ -249,7 +249,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect int nSpanV = 0 ; PtrOwner pCrvV( CreateCurveComposite()) ; if ( bGuideIsPolyLine ) { - if( pGuide->GetType() == CRV_LINE) + if ( pGuide->GetType() == CRV_LINE) nSpanV = 1 ; else if ( pGuide->GetType() == CRV_COMPO) nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ; @@ -260,7 +260,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ; else { const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ; - if( ! pGuideBez->IsRational()) + if ( ! pGuideBez->IsRational()) pCrvV->AddCurve( pGuide->Clone()) ; else pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ; @@ -297,7 +297,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect ICRVCOMPOPOVECTOR vCC ; INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ; int nMaxSpanV = nSpanV ; - for( int i = 0 ; i < nSpanU ; ++i) { + for ( int i = 0 ; i < nSpanU ; ++i) { const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ; for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) { Point3d ptCtrl = pSubCrv->GetControlPoint( j) ; @@ -327,7 +327,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect for ( int w = 0 ; w < int( vCC.size()) ; ++w) { const ICurveComposite* pCCOther = vCC[w] ; int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ; - if( nPropCheck != 0) + if ( nPropCheck != 0) mRep[w][z] = 1 ; } } @@ -337,11 +337,11 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect // conto in quante colonne di mRep la somma degli elementi è != 0 // questo numero va aggiunto all'attuale nSpanV int nSpanPlus = 0 ; - for( int z = 0 ; z < nMaxSpanV ; ++z) { + for ( int z = 0 ; z < nMaxSpanV ; ++z) { int nPosTot = 0 ; for ( int k = 0 ; k < int( mRep.size()) ; ++k ) nPosTot += mRep[k][z] ; - if( nPosTot != 0) + if ( nPosTot != 0) nSpanPlus += 1 ; } nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ; @@ -349,14 +349,14 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; //// aggiungo i punti di controllo alla superficie - //for( int i = 0 ; i < nSpanU ; ++i) { + //for ( int i = 0 ; i < nSpanU ; ++i) { // for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) { // const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ; // for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) { // const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ; - // if( pCL == nullptr) + // if ( pCL == nullptr) // return nullptr ; - // if( z == 0) { + // if ( z == 0) { // Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ; // pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ; // } @@ -367,13 +367,13 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect //} //// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO - //for( int i = 0 ; i < int( vCC.size()) ; ++i) { + //for ( int i = 0 ; i < int( vCC.size()) ; ++i) { // const ICurveComposite* pOffsetCrv = vCC[i] ; // for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) { // const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ; - // if( pCL == nullptr) + // if ( pCL == nullptr) // return nullptr ; - // if( z == 0) { + // if ( z == 0) { // Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ; // pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ; // } @@ -422,7 +422,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect //frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; //// porto la sezione nel sistema di riferimento del piano in cui giace //pCrvU->ToLoc( frStart) ; - //for( int i = 0 ; i < nSpanU ; ++i) { + //for ( int i = 0 ; i < nSpanU ; ++i) { // const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ; // for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) { // Point3d ptCtrl = pSubCrv->GetControlPoint( j) ; @@ -458,7 +458,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect // // aggiungo i punti di controllo alla superficie // for ( int z = 0 ; z < nSpanV ; ++z) { // const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ; - // if( pCrvBez == nullptr) + // if ( pCrvBez == nullptr) // return nullptr ; // for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) { // Point3d ptCtrl = pCrvBez->GetControlPoint( k) ; @@ -572,7 +572,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ; else { const ICurveBezier* pSectBez = GetCurveBezier( pSect) ; - if( ! pSectBez->IsRational()) + if ( ! pSectBez->IsRational()) pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! else pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ; @@ -775,12 +775,12 @@ GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol) { // verifico che le curve siano valide for ( int i = 0 ; i < int( vCrv.size()) ; ++i) { - if( vCrv[i] == nullptr || ! vCrv[i]->IsValid()) + if ( vCrv[i] == nullptr || ! vCrv[i]->IsValid()) return nullptr ; } // se ho solo due curve allora faccio la rigata - if( vCrv.size() == 2) + if ( vCrv.size() == 2) return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ; //trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado @@ -788,7 +788,7 @@ GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol) // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier // se la curva è già una bezier singola la tengo, sennò la converto ICURVEPOVECTOR vCrvBez ; - for( int c = 0 ; c < int( vCrv.size()) ; ++c){ + for ( int c = 0 ; c < int( vCrv.size()) ; ++c){ PtrOwner pCC( CreateCurveComposite()) ; if ( vCrv[c]->GetType() != CRV_BEZIER ) pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ; diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index c2d3097..8ccb23d 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -73,7 +73,7 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) return nullptr ; for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) { for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){ - if( vbInvert[vnPLIndMat[i][j]]) + if ( vbInvert[vnPLIndMat[i][j]]) vPL[vnPLIndMat[i][j]].Invert() ; } } @@ -165,7 +165,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert)) return nullptr ; for ( int i = 0 ; i < int( vPL.size()) ; ++i) { - if( vbInvert[i]) + if ( vbInvert[i]) vPL[i].Invert() ; } // verifico la direzione di estrusione diff --git a/SubtractProjectedFacesOnStmFace.cpp b/SubtractProjectedFacesOnStmFace.cpp index cc290c0..39538b5 100644 --- a/SubtractProjectedFacesOnStmFace.cpp +++ b/SubtractProjectedFacesOnStmFace.cpp @@ -302,7 +302,7 @@ SetTmpPropByOverlap( ICurveComposite* pCrvCheck, const int nInd, const ICurveCom // ultimo tratto di curva della Composita iniziale PtrOwner pCrvB( GetBasicCurveComposite( pCrvCheck->CopyParamRange( nInd + 1, pCrvCheck->GetCurveCount()))) ; if ( ! IsNull( pCrvB) && pCrvB->GetCurveCount() > 0 && pCrvB->IsValid()) - if( ! pCrvToReturn->AddCurve( Release( pCrvB))) { + if ( ! pCrvToReturn->AddCurve( Release( pCrvB))) { nStat = 2 ; return true ; } diff --git a/SurfAux.cpp b/SurfAux.cpp index bcdd829..ada55d4 100644 --- a/SurfAux.cpp +++ b/SurfAux.cpp @@ -42,7 +42,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) double dKnot = snData.vU[k] ; vU.push_back( dKnot) ; } - for( int j = 0 ; j < snData.nCPV ; ++j) { + for ( int j = 0 ; j < snData.nCPV ; ++j) { CNurbsData nuCurve ; nuCurve.bPeriodic = true ; nuCurve.bRat = snData.bRat ; @@ -66,12 +66,12 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie if ( snData.mCP.size() != nuCurve.vCP.size() ) { snData.mCP.resize( nuCurve.vCP.size()) ; - if( snData.bRat) + if ( snData.bRat) snData.mW.resize( nuCurve.vW.size()) ; } for ( int i = 0 ; i < snData.nCPU ; ++i) { snData.mCP[i][j] = nuCurve.vCP[i] ; - if( snData.bRat) { + if ( snData.bRat) { snData.mW[i][j] = nuCurve.vW[i] ; snData.mCP[i][j] *= nuCurve.vW[i] ; } @@ -91,7 +91,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData) double dKnot = snData.vV[k] ; vV.push_back( dKnot) ; } - for( int i = 0 ; i < snData.nCPU ; ++i) { + for ( int i = 0 ; i < snData.nCPU ; ++i) { CNurbsData nuCurve ; nuCurve.bPeriodic = true ; nuCurve.bRat = snData.bRat ; diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 2b79f3a..6dbbe3f 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -43,7 +43,6 @@ #include "/EgtDev/Include/EGkIntervals.h" #define EIGEN_NO_IO #include "/EgtDev/Extern/Eigen/Dense" -#include "/EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -357,16 +356,16 @@ SurfBezier::IsClosed( void) const m_bClosedU = AreSamePointApprox( m_vPtCtrl[GetInd(0,j)], m_vPtCtrl[GetInd(m_nDegU * m_nSpanU,j)]) ; // se ho la chiusura su entrambi i parametri ho la chiusura "in stile toro" - if( m_bClosedU && m_bClosedV) + if ( m_bClosedU && m_bClosedV) return true ; //verifico se ci sono dei poli che chiudono la superficie, per vedere se ho la chiusura "in stile sfera, da polo a polo" ( classica superficie di rivoluzione) CalcPoles() ; // chiusa in U e con poli sugli altri 2 lati - if( m_bClosedU && ! m_bClosedV && m_vbPole[0] && m_vbPole[2]) + if ( m_bClosedU && ! m_bClosedV && m_vbPole[0] && m_vbPole[2]) return true ; // chiusa in V e con poli sugli altri due lati - if( m_bClosedV && ! m_bClosedU && m_vbPole[1] && m_vbPole[3]) + if ( m_bClosedV && ! m_bClosedU && m_vbPole[1] && m_vbPole[3]) return true ; // se ho due lati opposti che sono dei poli e sono anche coincidenti allora la superficie potrebbe essere chiusa "in stile sfera a saccoccia" @@ -869,7 +868,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc) m_bTrimmed = true ; m_pTrimReg = sbSrc.m_pTrimReg->Clone() ; } - m_pSTM = sbSrc.GetAuxSurf()->Clone() ; + if( sbSrc.GetAuxSurf() != nullptr) + m_pSTM = sbSrc.GetAuxSurf()->Clone() ; for ( int i = 0 ; i < int( sbSrc.m_mCCEdge.size()) ; ++i) { m_mCCEdge.emplace_back() ; for ( int j = 0 ; j < int( sbSrc.m_mCCEdge[i].size()) ; ++j ) { @@ -1389,7 +1389,7 @@ SurfBezier::GetCurveOnU( double dV) const for ( int s = 0 ; s < m_nSpanU ; ++ s) { PtrOwner pCbz( CreateBasicCurveBezier()) ; pCbz->Init( m_nDegU, m_bRat) ; - for( int j = 0 ; j < m_nDegU ; ++j) + for ( int j = 0 ; j < m_nDegU ; ++j) pCbz->SetControlPoint( s * m_nDegU + j, GetControlPoint( GetInd( s * m_nDegU + j , nV * m_nDegV), &bOk), GetControlWeight( GetInd( s * m_nDegU + j , nV * m_nDegV), &bOk)) ; pCrvCo->AddCurve( Release( pCbz)) ; } @@ -1399,7 +1399,7 @@ SurfBezier::GetCurveOnU( double dV) const for ( int s = 0 ; s < m_nSpanU ; ++ s) { PtrOwner pCbz( CreateBasicCurveBezier()) ; pCbz->Init( m_nDegU, m_bRat) ; - for( int j = 0 ; j < m_nDegU ; ++j) + for ( int j = 0 ; j < m_nDegU ; ++j) pCbz->SetControlPoint( s * m_nDegU + j, GetControlPoint( GetInd( s * m_nDegU + j , nV * m_nDegV), &bOk)) ; pCrvCo->AddCurve( Release( pCbz)) ; } @@ -1501,7 +1501,7 @@ SurfBezier::GetCurveOnV( double dU) const for ( int s = 0 ; s < m_nSpanV ; ++ s) { PtrOwner pCbz( CreateBasicCurveBezier()) ; pCbz->Init( m_nDegV, m_bRat) ; - for( int j = 0 ; j < m_nDegV ; ++j) + for ( int j = 0 ; j < m_nDegV ; ++j) pCbz->SetControlPoint( s * m_nDegV + j, GetControlPoint( GetInd( s * m_nDegV + j , nU * m_nDegU), &bOk), GetControlWeight( GetInd( s * m_nDegV + j , nU * m_nDegU), &bOk)) ; pCrvCo->AddCurve( Release( pCbz)) ; } @@ -1511,7 +1511,7 @@ SurfBezier::GetCurveOnV( double dU) const for ( int s = 0 ; s < m_nSpanV ; ++ s) { PtrOwner pCbz( CreateBasicCurveBezier()) ; pCbz->Init( m_nDegV, m_bRat) ; - for( int j = 0 ; j < m_nDegV ; ++j) + for ( int j = 0 ; j < m_nDegV ; ++j) pCbz->SetControlPoint( s * m_nDegV + j, GetControlPoint( GetInd( s * m_nDegV + j , nU * m_nDegU), &bOk)) ; pCrvCo->AddCurve( Release( pCbz)) ; } @@ -1880,8 +1880,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons // aggiorno la chiusura della superficie m_bClosedU = m_bClosedU || Tree.IsClosedU() ; m_bClosedV = m_bClosedV || Tree.IsClosedV() ; - //// salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria - // UpdateEdgesFromTree( Tree) ; // ora viene fatto nella GetPolygons } //// per usare i polygon basic////////////////////// @@ -1961,7 +1959,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons // riordino il vettore dei punti su cui non ho fatto la triangolazione if ( vPL.size() == 2) { - //if( vPnt.size() != vPnt3d.size()) + //if ( vPnt.size() != vPnt3d.size()) // return nullptr ; PNTVECTOR vPntOrd ; if ( bTriangulatedIn3D) { @@ -1978,7 +1976,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons if ( vPL.size() == 1) { vPnt3d = vPnt ; PNTVECTOR vPnt2d ; - for( int i = 0 ; i < int( vPL.size()) ; ++i) { + for ( int i = 0 ; i < int( vPL.size()) ; ++i) { PolyLine& pl = vPL[i] ; Point3d pt ; pl.GetFirstPoint( pt) ; //vPnt2D.push_back( pt) ; @@ -2039,37 +2037,37 @@ SurfBezier::ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, int nPoints = 0 ; bool bInverted = false ; for ( int poly = 0 ; poly < int( vPL.size()) ; ++poly ) { - if( vbPolyChecked[poly]) + if ( vbPolyChecked[poly]) continue ; PolyLine pl = vPL[poly] ; nInd = 0 ; Point3d ptPoly ; pl.GetFirstPoint( ptPoly) ; bool bFound = false ; - if( AreSamePointExact( pt, ptPoly)){ + if ( AreSamePointExact( pt, ptPoly)){ nPoints = pl.GetPointNbr() ; nPoly = poly ; bFound = true ; pl.GetNextPoint( ptPoly) ; - if( ! AreSamePointExact( vPnt[p+1], ptPoly)) + if ( ! AreSamePointExact( vPnt[p+1], ptPoly)) bInverted = true ; break ; } while ( pl.GetNextPoint( ptPoly) && ! bFound) { ++ nInd ; - if( AreSamePointExact( pt, ptPoly)) { + if ( AreSamePointExact( pt, ptPoly)) { nPoints = pl.GetPointNbr() ; nPoly = poly ; bFound = true ; pl.GetNextPoint( ptPoly) ; - if( ! AreSamePointExact( vPnt[p+1], ptPoly)) + if ( ! AreSamePointExact( vPnt[p+1], ptPoly)) bInverted = true ; break ; } } - if( bFound) + if ( bFound) break ; } - if( nInd == 0) { + if ( nInd == 0) { Point3d ptPoly ; vPLToOrd[nPoly].GetFirstPoint( ptPoly) ; vPntOrd.push_back( ptPoly) ; @@ -2086,7 +2084,7 @@ SurfBezier::ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, else { PNTVECTOR vPntToRotate ; Point3d ptPoly ; - if( ! bInverted) { + if ( ! bInverted) { vPLToOrd[nPoly].GetFirstPoint( ptPoly) ; vPntToRotate.push_back( ptPoly) ; while ( vPLToOrd[nPoly].GetNextPoint( ptPoly)) @@ -2119,7 +2117,7 @@ SurfBezier::ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangula for ( int i = 0 ; i < int( vPLToOrd.size()) ; ++i) { Point3d pt ; vPLToOrd[i].GetFirstPoint( pt) ; vPntPolyToOrd.push_back( pt) ; - while( vPLToOrd[i].GetNextPoint( pt)) + while ( vPLToOrd[i].GetNextPoint( pt)) vPntPolyToOrd.push_back( pt) ; } // costruisco il vettore con i punti delle polyline in ordine @@ -2127,7 +2125,7 @@ SurfBezier::ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangula for ( int i = 0 ; i < int( vPL.size()) ; ++i) { Point3d pt ; vPL[i].GetFirstPoint( pt) ; vPntPoly.push_back( pt) ; - while( vPL[i].GetNextPoint( pt)) + while ( vPL[i].GetNextPoint( pt)) vPntPoly.push_back( pt) ; } BOOLVECTOR vbPntChecked( vPnt.size()) ; @@ -2136,7 +2134,7 @@ SurfBezier::ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangula for ( int p = 0 ; p < int( vPntPoly.size()) ; ++p) { Point3d pt = vPntPoly[p] ; for ( int t = 0 ; t < int( vPnt.size()) ; ++t) { - if( vbPntChecked[t]) + if ( vbPntChecked[t]) continue ; Point3d ptToCheck = vPnt[t] ; if ( AreSamePointExact( pt, ptToCheck)) { @@ -2256,14 +2254,14 @@ SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV, double* dUVCopy, bo if ( bUOrV) { if ( dUVTest < 0) dUVTest = 0 ; - else if ( dUVTest > m_nSpanU * SBZ_TREG_COEFF ) - dUVTest = m_nSpanU * SBZ_TREG_COEFF ; + else if ( dUVTest > m_nSpanU ) + dUVTest = m_nSpanU ; } else { if ( dUVTest < 0) dUVTest = 0 ; - else if ( dUVTest > m_nSpanV * SBZ_TREG_COEFF ) - dUVTest = m_nSpanV * SBZ_TREG_COEFF ; + else if ( dUVTest > m_nSpanV ) + dUVTest = m_nSpanV ; } if ( bModifyOrig) dUV = dUVTest ; @@ -2299,6 +2297,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& BOOLVECTOR vbThroughEdge ; if ( ! UnprojectPoint( pt3D, pt2D, pt3DEnd, &bThroughEdge, pPlCut)) return false ; + pt2D *= SBZ_TREG_COEFF ; vbThroughEdge.push_back( bThroughEdge) ; // aggiungo tutti i successivi @@ -2307,7 +2306,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& // per il primo punto non mi interessa sapere se è passato attraverso un edge, tanto ha già le coordinate parametriche giuste bThroughEdge = false ; int nRejected = 0 ; - for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { + for ( int i = 0 ; i < pCC->GetCurveCount() ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; Point3d pt3DPrev = pt3D ; Point3d pt2DPrev = pt2D ; @@ -2343,6 +2342,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& pCrv->GetEndPoint( pt3D) ; if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev, &bThroughEdge, pPlCut)) return false ; + pt2D *= SBZ_TREG_COEFF ; // se il precedente era passato attraverso l'edge ed era un edge di polo allora devo sistemare le coordinate if ( bPrevIsPole) { @@ -2361,10 +2361,10 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& ++ nRejected ; continue ; } + double dParamH, dParamL ; + dParamH = m_nSpanV * SBZ_TREG_COEFF ; + dParamL = m_nSpanU * SBZ_TREG_COEFF ; if ( bThroughEdge && vbThroughEdge.back()) { - double dParamH, dParamL ; - dParamH = m_nSpanV * SBZ_TREG_COEFF ; - dParamL = m_nSpanU * SBZ_TREG_COEFF ; // sia questo punto che il precedente sono su un edge, ma il segmento che li unisce non è parallelo ad un edge // ( i punti per periodicità hanno coordinate diverse anche se dovrebbero averle uguali, quindi il segmento attraversa tutto lo spazio parametrico, anche se in realtà è lungo il bordo di chiusura) // potrei star tracciando un taglio sul bordo di chiusura @@ -2375,6 +2375,38 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& continue ; } } + // se il primo e l'ultimo punto sono entrambi su edge e indicano un attraversamento, controllo che siano da lati opposti del parametrico + // altrimenti li porto dal lato del punto successivo/precedente + if ( bThroughEdge && pCC->IsClosed() && i == pCC->GetCurveCount() - 1 && vbThroughEdge[0] && ( m_bClosedU || m_bClosedV)) { + if ( m_bClosedU) { + if ( abs( vBPnt[0].first.x - vBPnt[0].second.x) > 0.5 * dParamL){ + if (dParamL - vBPnt[0].second.x < 0.5 * dParamL) + vBPnt[0].first.x = dParamL ; + else + vBPnt[0].first.x = 0 ; + } + if ( abs( pt2D.x - pt2DPrev.x) > 0.5 * dParamL){ + if ( dParamL - pt2DPrev.x < 0.5 * dParamL) + pt2D.x = dParamL ; + else + pt2D.x = 0 ; + } + } + if ( m_bClosedV) { + if ( abs( vBPnt[0].first.y - vBPnt[0].second.y) > 0.5 * dParamH){ + if (dParamH - vBPnt[0].second.y < 0.5 * dParamH) + vBPnt[0].first.y = dParamH ; + else + vBPnt[0].first.y = 0 ; + } + if ( abs( pt2D.y - pt2DPrev.y) > 0.5 * dParamH){ + if ( dParamH - pt2DPrev.y < 0.5 * dParamH) + pt2D.y = dParamH ; + else + pt2D.y = 0 ; + } + } + } vbThroughEdge.push_back( bThroughEdge) ; vBPnt.emplace_back( BIPOINT( pt2DPrev, pt2D)) ; if ( ! chainC.AddCurve( i + 1 - nRejected, pt2DPrev, vtDir, pt2D, vtDir)) @@ -2744,7 +2776,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // concateno le curve 3d ChainCurves chainC ; - double dToler = EPS_SMALL ; + double dToler = 10 * EPS_SMALL ; chainC.Init( false, dToler, int( vBPnt.size())) ; for ( int i = 0 ; i < int( vBPnt.size()) ; ++ i) { Vector3d vtDir = vBPnt[i].second - vBPnt[i].first ; @@ -2920,9 +2952,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche const ISurfTriMesh* pSurfTm = GetAuxSurfRefined() ; int nTriaIndex = nT ; + INTVECTOR vnT ; if ( nT == -1) { DistPointSurfTm distPtStm0( ptI, *pSurfTm) ; distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; + distPtStm0.GetMinDistTriaIndices( vnT) ; } // aggiungo il primo punto // devo subito capire se sono in un polo o no @@ -2931,9 +2965,9 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in bool bNearPole = false ; // devo capire se il triangolo di riferimento ha un vertice in un polo INTVECTOR vInters(4) ; fill( vInters.begin(), vInters.end(), 0) ; - // se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles - if ( int( m_vbPole.size()) == 0) - return false ; + // se necessario calcolo i poli + if ( m_vbPole.empty()) + CalcPoles() ; if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3] || m_bClosedU || m_bClosedV) { // scorro sugli edge for ( int c = 0 ; c < 4 ; ++c) { @@ -2962,10 +2996,22 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in return false ; if ( bThroughEdge != nullptr) *bThroughEdge = true ; - Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * 3 * EPS_SMALL ; + Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * 10 * EPS_SMALL ; // ricalcolo il triangolo di appartenenza + int nTriaOld = nTriaIndex ; DistPointSurfTm dPtStm( ptI2, *pSurfTm) ; dPtStm.GetMinDistTriaIndex( nTriaIndex) ; + // se ho trovato un nuovo triangolo, controllo che questo fosse nella lista dei triangoli equidistanti dal punto originale + // sennò ripeto il conto con meno scostamento + if( nTriaOld != nTriaIndex) { + auto iter = find( vnT.begin(), vnT.end(),nTriaIndex) ; + int nIdTria = distance( vnT.begin(), iter) ; + if( nIdTria > ssize( vnT) - 1) { + ptI2 = ptI + ( ptIPrevOrNext - ptI) * 5 * EPS_SMALL ; + DistPointSurfTm dPtStm2( ptI2, *pSurfTm) ; + dPtStm2.GetMinDistTriaIndex( nTriaIndex) ; + } + } } } @@ -2973,9 +3019,12 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in int nVert[3] ; pSurfTm->GetTriangle( nTriaIndex, nVert) ; PNTVECTOR vPtPa(3) ; - pSurfTm->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ; - pSurfTm->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ; - pSurfTm->GetVertexParam( nVert[2], vPtPa[2].x,vPtPa[2].y) ; + pSurfTm->GetVertexParam( nVert[0], vPtPa[0].x, vPtPa[0].y) ; + vPtPa[0] *= SBZ_TREG_COEFF ; + pSurfTm->GetVertexParam( nVert[1], vPtPa[1].x, vPtPa[1].y) ; + vPtPa[1] *= SBZ_TREG_COEFF ; + pSurfTm->GetVertexParam( nVert[2], vPtPa[2].x, vPtPa[2].y) ; + vPtPa[2] *= SBZ_TREG_COEFF ; PNTVECTOR vPT(3) ; pSurfTm->GetVertex( nVert[0], vPT[0]) ; pSurfTm->GetVertex( nVert[1], vPT[1]) ; @@ -2985,7 +3034,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in int nEdge = -1 ; // do per scontato che al più un vertice possa essere in un polo if ( m_vbPole[0] || m_vbPole[2]) { - for( int p = 0 ; p < 3 ; ++p) { + for ( int p = 0 ; p < 3 ; ++p) { if ( ( m_vbPole[0] && vPtPa[p].y > m_nSpanV * SBZ_TREG_COEFF - EPS_SMALL ) ) { bNearPole = true ; nVertOnPole = p ; @@ -2999,7 +3048,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } else if ( m_vbPole[1] || m_vbPole[3]) { - for( int p = 0 ; p < 3 ; ++p) { + for ( int p = 0 ; p < 3 ; ++p) { if ( ( m_vbPole[3] && vPtPa[p].x > m_nSpanU * SBZ_TREG_COEFF - EPS_SMALL)) { bNearPole = true ; nVertOnPole = p ; @@ -3090,7 +3139,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for (int ed : vEdgesClosed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { - if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) + if ( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) vOn[p] = ed ; } } @@ -3128,7 +3177,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for (int ed = 0 ; ed < 4 ; ++ed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { - if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) + if ( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) vOn[p] = ed ; } } @@ -3156,7 +3205,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( vPtPa[p].x > dRightX ) dRightX= vPtPa[p].x ; // se un vertice è su un lato di chiusura, visto che sono vicino ad un polo, mi accerto che un lato del triangolo sia SUL lato di chiusura - if( m_bClosedU && bOneVertexOnClosureButNotPole) { + if ( m_bClosedU && bOneVertexOnClosureButNotPole) { dRightX = ( dParamL - vPtPa[p].x > vPtPa[p].x ? 0 : dParamL) ; break ; } @@ -3166,7 +3215,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in dRightX = nEdge == 1 ? 0 : dParamL ; if ( vPtPa[p].y > dRightY ) dRightY = vPtPa[p].y ; - if( m_bClosedV && bOneVertexOnClosureButNotPole) { + if ( m_bClosedV && bOneVertexOnClosureButNotPole) { dRightY = ( dParamH - vPtPa[p].y > vPtPa[p].y ? 0 : dParamH) ; break ; } @@ -3190,6 +3239,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in ptSP = vPtPa[1] ; else if ( AreSamePointApprox(ptI, vPT[2])) ptSP = vPtPa[2] ; + // restituisco il punto nel parametrico riscalato + ptSP / SBZ_TREG_COEFF ; return true ; } // calcolo approssimativamente le coordinate nello spazio parametrico del punto di intersezione @@ -3226,8 +3277,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in mB.col(1) << vPtPa[1].x, vPtPa[1].y, 0 ; mB.col(2) << vPtPa[2].x, vPtPa[2].y, 0 ; Eigen::Vector3d ptParam = mB * x ; - IncreaseUV( ptSP.x, ptParam.x(), true) ; - IncreaseUV( ptSP.y, ptParam.y(), false) ; + // restituisco il punto nel parametrico riscalato + IncreaseUV( ptSP.x, ptParam.x() / SBZ_TREG_COEFF, true) ; + IncreaseUV( ptSP.y, ptParam.y() / SBZ_TREG_COEFF, false) ; + return true ; } @@ -3252,7 +3305,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d if ( ! UnprojectPointFromStm( -1, ptI, ptParam, IntLineTriaType::ILTT_IN, ptIPrev, bThroughEdge)) return false ; Point3d ptBez ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + GetPointD1D2( ptParam.x, ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto double dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : abs(DistPointPlane( ptBez, *pPlCut)) ; @@ -3276,16 +3329,14 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d dDistPre = dDistNew ; // derivata in U Point3d ptIBzNew1 ; - //GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; double dUh ; IncreaseUV( ptParam.x, dh, true, &dUh, false) ; - GetPointD1D2( dUh / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + GetPointD1D2( dUh, ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; dDist0 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew1) : abs(DistPointPlane( ptIBzNew1, *pPlCut)) ; dfdU = ( dDist0 - dDistPre) / dh ; // derivata in V Point3d ptIBzNew2 ; - //GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; double dVh ; IncreaseUV( ptParam.y, dh, false, &dVh, false) ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, dVh / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + GetPointD1D2( ptParam.x, dVh, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; dDist1 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew2) : abs(DistPointPlane( ptIBzNew2, *pPlCut)) ; dfdV = ( dDist1 - dDistPre) / dh ; } @@ -3296,7 +3347,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d vtDir.Set( - dfdU, - dfdV, 0) ; if ( ! vtDir.Normalize() ) vtDir.Set( - dfdU / dSSum, - dfdV / dSSum, 0) ; - if( ! vtDir.IsValid()) + if ( ! vtDir.IsValid()) return false ; dr = dDistPre / dASum ; // in modalità Retry riduco lo spostamento @@ -3313,7 +3364,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d Point3d ptCopy = ptParam ; IncreaseUV( ptParam, vtDir, nullptr, true) ; // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + GetPointD1D2( ptParam.x, ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : abs(DistPointPlane( ptBez, *pPlCut)) ; dApproach = dDistPre - dDistNew ; @@ -3340,16 +3391,16 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d // devo distinguere il caso di un triangolo a metà dello spazio, con un vertice su un lato di polo, ma senza vertici su lati di chiusura if ( bThroughEdge != nullptr && *bThroughEdge) { if ( m_bClosedU) { - if ( ptParam.x < 1) + if ( ptParam.x < EPS_SMALL) ptParam.x = 0 ; - else if ( abs( m_nSpanU * SBZ_TREG_COEFF - ptParam.x) < 1) - ptParam.x = m_nSpanU * SBZ_TREG_COEFF ; + else if ( abs( m_nSpanU - ptParam.x) < EPS_SMALL) + ptParam.x = m_nSpanU ; } if ( m_bClosedV) { - if ( ptParam.y < 1) + if ( ptParam.y < EPS_SMALL) ptParam.y = 0 ; - else if ( abs( m_nSpanV * SBZ_TREG_COEFF - ptParam.y) < 1) - ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; + else if ( abs( m_nSpanV - ptParam.y) < EPS_SMALL) + ptParam.y = m_nSpanV ; } } @@ -3429,7 +3480,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const if ( ! m_bClosedV ) { if ( ! m_vbPole[2]) { // se superficie è chiusa lungo il parametro U, ma non lo è lungo il parametro V allora avrò due curve separate( un cilindro) - if( m_bClosedU) + if ( m_bClosedU) vCC.emplace_back( CreateCurveComposite()) ; vCC.back()->AddCurve( GetSingleEdge3D( bLineOrBezier, 2)) ; } @@ -3437,7 +3488,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const if ( ! m_bClosedU ) { if ( ! m_vbPole[3]) { // se superficie è chiusa lungo il parametro V, ma non lo è lungo il parametro U allora avrò due curve separate( un cilindro) - if( m_bClosedV) + if ( m_bClosedV) vCC.emplace_back( CreateCurveComposite()) ; vCC.back()->AddCurve( GetSingleEdge3D( bLineOrBezier, 3)) ; } @@ -3708,7 +3759,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const // qui portei estrarre una funzione che proietta curve dal parametrico al 3D // scorro i gruppi di loop 2D formati da loop che partecipano alla formazione dello stesso loop nel 3D ICRVCOMPOPOVECTOR vpCCOpen ; - for( int i = 0 ; i < int( m_vCCLoop.size()); ++i) { + for ( int i = 0 ; i < int( m_vCCLoop.size()); ++i) { vpCCOpen.emplace_back(CreateBasicCurveComposite()) ; PolyLine pl3D ; // la composita è una spezzata composta da linee, quindi la ricostruisco come polyline in 3D @@ -3736,7 +3787,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const PtrOwner pCC( vpCCOpen[k]->Clone()) ; vbAdded[k] = true ; bool bAddedOne = true ; - while( bAddedOne) { + while ( bAddedOne) { bAddedOne = false ; for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { if ( vbAdded[t]) @@ -3871,7 +3922,7 @@ SurfBezier::IsPlanar( void) const PolyLine plApprox ; Plane3d plPlane ; - if( ! m_bTrimmed) { + if ( ! m_bTrimmed) { // costruisco il contorno della superficie unendo gli edge e chiedo se la polyline è piana. PtrOwner pCCEdge( GetSingleEdge3D( false, 0)) ; pCCEdge->AddCurve( GetSingleEdge3D( false, 1)) ; @@ -3994,7 +4045,7 @@ SurfBezier::CreateByRegion( const POLYLINEVECTOR& vPL) // creo una superficie piana grande come il box della curva nel suo piano e poi la trimmo POLYLINEVECTOR vPLFlat = vPL ; BBox3d bboxContour ; - for( int i = 0 ; i < int( vPLFlat.size()) ; ++i) { + for ( int i = 0 ; i < int( vPLFlat.size()) ; ++i) { // porto le polilinee nel riferimento del loro piano e ne recupero il box vPLFlat[i].ToLoc(frContour) ; BBox3d bboxLoop ; @@ -4027,7 +4078,7 @@ SurfBezier::CreateByRegion( const POLYLINEVECTOR& vPL) ICRVCOMPOPOVECTOR vCCClosed ; for ( int i = 0 ; i < int( vPL.size()) ; ++i) { ICurveComposite* pCC( CreateBasicCurveComposite()) ; - if( pCC == nullptr || ! pCC->FromPolyLine( vPL[i]) || ! pCC->IsValid()) + if ( pCC == nullptr || ! pCC->FromPolyLine( vPL[i]) || ! pCC->IsValid()) return false ; if ( ! AddCurveCompoToCuts( pCC, vCCOpen, vCCClosed)) return false ; // o metto un continue? @@ -4369,7 +4420,7 @@ ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, I int nMin = 0 ; dMinDist = INFINITO ; for ( int i = 0 ; i < int( vDistVert.size()) ; ++i) { - if( get<0>(vDistVert[i]) < dMinDist) { + if ( get<0>(vDistVert[i]) < dMinDist) { dMinDist = get<0>(vDistVert[i]) ; nMin = i ; } @@ -4425,7 +4476,7 @@ GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, INTVECTOR& vEdgeSplit) vEdgeSplit[nP] = true ; } - if( ! bClosed) + if ( ! bClosed) vEdgeSplit[0] = false ; return true ; @@ -4497,14 +4548,14 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int if ( nDegU0 != nDegU1) { while ( nDegU0 < nDegU1) { CurveComposite CC ; - for( int k = 0 ; k < nSpanU0 ; ++k) + for ( int k = 0 ; k < nSpanU0 ; ++k) CC.AddCurve( BezierIncreaseDegree( GetCurveBezier( CrvU0.GetCurve( k)))) ; ++nDegU0 ; CrvU0 = CC ; } while ( nDegU0 > nDegU1) { CurveComposite CC ; - for( int k = 0 ; k < nSpanU0 ; ++k) + for ( int k = 0 ; k < nSpanU0 ; ++k) CC.AddCurve( BezierIncreaseDegree( GetCurveBezier( CrvU1.GetCurve( k)))) ; ++nDegU1 ; CrvU1 = CC ; @@ -4550,7 +4601,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int for ( int k = 0 ; k < nSpanU0 ; ++k ) { const ICurveBezier* pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( k)) ; for ( int i = 0 ; i < nDegU + 1 ; ++i ) { - if( i != nDegU && !( i == 0 && k == 0)) + if ( i != nDegU && !( i == 0 && k == 0)) continue ; Point3d ptCtrl = pSubCrv0->GetControlPoint( i) ; if ( bRat0) @@ -4565,7 +4616,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int for ( int k = 0 ; k < nSpanU1 ; ++k ) { const ICurveBezier* pSubCrv1 = GetCurveBezier( CrvU1.GetCurve( k)) ; for ( int i = 0 ; i < nDegU1 + 1 ; ++i ) { - if( i != nDegU && !( i == 0 && k == 0)) + if ( i != nDegU && !( i == 0 && k == 0)) continue ; Point3d ptCtrl = pSubCrv1->GetControlPoint( i) ; if ( bRat1) @@ -4614,7 +4665,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } // reinizializzo la superficie con il nuovo numero di span in U nSpanU = nSpanU0 + nRep1 ; - if( nSpanU != nSpanU1 + nRep0) + if ( nSpanU != nSpanU1 + nRep0) LOG_DBG_ERR( GetEGkLogger(), "There could be an errore in the creation of a ruled surface in mode RLT_B_MINDIST") ; if ( nSpanU < max(nSpanU0, nSpanU1)) nSpanU = max(nSpanU0, nSpanU1) ; @@ -4659,7 +4710,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int for ( int z = vPnt0Match[i].second ; z <= vPnt0Match[i+1].second ; ++z) bSubCurveAddedFirst = bSubCurveAddedFirst && vPnt1Match[z].second != i ; - if( bSubCurveAddedFirst) { + if ( bSubCurveAddedFirst) { // aggiungo una sottocurva dalla curva U0 pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { @@ -4672,7 +4723,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } // ripeto l'ultimo punto aggiunto per il numero di curve balzate - 1 della curva U1 - for( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { + for ( int k = 0 ; k < nIndMatchNext - nIndMatch - 1 ; ++k) { pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( i != 0 ? i - 1 : i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { int nPoint = i == 0 && ! bSubCurveAddedFirst ? 0 : nDegU ; @@ -4684,7 +4735,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nCount0 ; } // se non l'ho già aggiunta prima aggiungo una sottocurva della U0 - if( ! bSubCurveAddedFirst) { + if ( ! bSubCurveAddedFirst) { pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( i)) ; for ( int j = nCount0 == 0 ? 0 : 1 ; j < nLastPoint ; ++j) { if ( ! bRat0) @@ -4697,7 +4748,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // aggiungo tutte le sottocurve che ho balzato della curva U1 - for( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { + for ( int k = 0 ; k < nIndMatchNext - nIndMatch ; ++k) { pSubCrv0 = GetCurveBezier( CrvU1.GetCurve( nIndMatch + k)) ; for ( int j = nCount1 == 0 ? 0 : 1 ; j < nLastPoint ; ++j ) { if ( ! bRat) @@ -4715,7 +4766,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // riaggiungo l'ultimo punto della U0 const ICurveBezier* pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( nSpanU0 - 1)) ; int nPoint = nDegU ; - while( nCount0 < nSpanU) { + while ( nCount0 < nSpanU) { for ( int j = 1 ; j < nLastPoint ; ++j) { if ( ! bRat0) SetControlPoint( nCount0 * nDegU + j, pSubCrv0->GetControlPoint( nPoint)) ; @@ -4727,7 +4778,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // aggiungo le restanti sottocurve della curva U1 int nCrv1 = vPnt0Match.back().second ; - while( nCrv1 < nSpanU1) { + while ( nCrv1 < nSpanU1) { const ICurveBezier* pSubCrv1 = GetCurveBezier( CrvU1.GetCurve( nCrv1)) ; for ( int j = 1 ; j < nLastPoint ; ++j) { if ( ! bRat1) @@ -4762,7 +4813,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // prendo la polyline con più punti e scelgo a quali punti dell'altra polyline vanno associati FindMatchByParam( plU0, plU1, vMatch,nLong) ; - for( int i = 0 ; i < int( vMatch.size() - 1) ; ++i) { + for ( int i = 0 ; i < int( vMatch.size() - 1) ; ++i) { int nCount = i ; // span in U aggiunte // scorro i punti della polyline più lunga // se il punto corrente e il successivo sono associati allo stesso punto dell'altra polyline @@ -4875,7 +4926,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int IntersCurvePlane icp( ccPoly0, ptP1, vtDir) ; double dParam ; Point3d ptJoint ; - if( icp.GetIntersCount() > 0) + if ( icp.GetIntersCount() > 0) icp.GetIntersPointNearTo( ptP1, ptJoint, dParam) ; else { DistPointCurve dpc( ptP1, CrvU0, false) ; @@ -4886,14 +4937,14 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // capisco se il punto avrà bisogno di aggiungere uno split sull'altra curva o no int nParam = int( dParam) ; Point3d ptNearestJoint ; // punto più vicino di joint già esistente sulla curva U0 - if( nParam == nSpanU0) + if ( nParam == nSpanU0) CrvU0.GetCurve( nParam - 1)->GetEndPoint( ptNearestJoint) ; - else if( dParam - nParam > 0.5) + else if ( dParam - nParam > 0.5) CrvU0.GetCurve( nParam)->GetEndPoint( ptNearestJoint) ; else CrvU0.GetCurve( nParam)->GetStartPoint( ptNearestJoint) ; //se sono troppo vicino ad uno split esistente allora non faccio nulla - if( abs(dParam - round( dParam)) < 100 * EPS_PARAM || Dist( ptJoint, ptNearestJoint) < 50 * EPS_SMALL) { + if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM || Dist( ptJoint, ptNearestJoint) < 50 * EPS_SMALL) { dParam = round( dParam) ; } @@ -4912,7 +4963,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int Point3d ptJoint ; Vector3d vtDir ; CrvU0.GetCurve( vPnt0.size() - 1)->GetEndDir( vtDir) ; IntersCurvePlane icp( ccPoly1, ptP0, vtDir) ; - if( icp.GetIntersCount() > 0) { + if ( icp.GetIntersCount() > 0) { icp.GetIntersPointNearTo( ptP0, ptJoint, dParam) ; } else { @@ -4924,9 +4975,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // capisco se il punto avrà bisogno di aggiungere uno split sull'altra curva o no int nParam = int( dParam) ; Point3d ptNearestJoint ; // punto più vicino di joint già esistente sulla curva U1 - if( nParam == nSpanU1) + if ( nParam == nSpanU1) CrvU1.GetCurve( nParam - 1)->GetEndPoint( ptNearestJoint) ; - else if( dParam - nParam > 0.5) + else if ( dParam - nParam > 0.5) CrvU1.GetCurve( nParam)->GetEndPoint( ptNearestJoint) ; else CrvU1.GetCurve( nParam)->GetStartPoint( ptNearestJoint) ; @@ -4962,16 +5013,20 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int vPairs.emplace_back( 0, 0) ; bool bAdvance = true ; // verifico i match effettivi tra le polyline - while( bAdvance) { + while ( bAdvance) { + if ( c > ssize(vMatch0) - 1 || j > ssize( vMatch1) - 1) { + LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: le due curve potrebbero non avere forme coerenti") ; + return false ; + } double dParam0 = vMatch0[c].second ; Point3d ptJoint0 = vMatch0[c].first ; double dParam1 = vMatch1[j].second ; Point3d ptJoint1 = vMatch1[j].first ; - if( bIsClosed1 && dParam0 > nSpanU1 - EPS_SMALL && c < ssize( vMatch0) / 2) { + if ( bIsClosed1 && dParam0 > nSpanU1 - EPS_SMALL && c < ssize( vMatch0) / 2) { dParam0 = 0 ; vMatch0[c].second = dParam0 ; } - if( bIsClosed0 && dParam1 > nSpanU0 - EPS_SMALL && j < ssize( vMatch1) / 2) { + if ( bIsClosed0 && dParam1 > nSpanU0 - EPS_SMALL && j < ssize( vMatch1) / 2) { dParam1 = 0 ; vMatch1[j].second = dParam1 ; } @@ -4984,18 +5039,18 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nSplit1 = vdSplit1.size() ; int nSplit0 = vdSplit0.size() ; // se con una polyline sono arrivato alla fine non posso più avanzare - if( c == vMatch0.size()) + if ( c == vMatch0.size()) bAdvance0 = false ; - if( j == vMatch1.size()) + if ( j == vMatch1.size()) bAdvance1 = false ; // se trovo che ho uno spigolo allora procedo con la gestione spigoli - if( vEdgeSplit0[c+1] || vEdgeSplit1[j+1]) { + if ( vEdgeSplit0[c+1] || vEdgeSplit1[j+1]) { bAdvance0 = false ; bAdvance1 = false ; } if ( bAdvance0) { - if( c < dLastParamMatch1 + EPS_SMALL) + if ( c < dLastParamMatch1 + EPS_SMALL) ++c ; // ho match con lo start if ( dParam0 < EPS_SMALL) { @@ -5011,8 +5066,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } else { // ho un match con una joint esistente - if( dParam0 - int( dParam0) < EPS_SMALL) { - if( dParam0 > dLastParamMatch0) + if ( dParam0 - int( dParam0) < EPS_SMALL) { + if ( dParam0 > dLastParamMatch0) vPairs.emplace_back( c + nSplit0, j + nSplit1 + 1) ; else vPairs.emplace_back( c + nSplit0, j + nSplit1) ; @@ -5028,11 +5083,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ptLastPointMatch0 = ptJoint0 ; dLastParamMatch1 = c ; ptLastPointMatch1 = vPnt0[c] ; - if( bPerfectMatch) + if ( bPerfectMatch) ++j ; } if ( bAdvance1 && ! bPerfectMatch) { - if( j < dLastParamMatch0 + EPS_SMALL) + if ( j < dLastParamMatch0 + EPS_SMALL) ++j ; // ho un match con lo start if ( dParam1 < EPS_SMALL) { @@ -5048,8 +5103,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } else { // ho un match con una joint esistente - if( dParam1 - int( dParam1) < EPS_SMALL) { - if( dParam1 > dLastParamMatch1) + if ( dParam1 - int( dParam1) < EPS_SMALL) { + if ( dParam1 > dLastParamMatch1) vPairs.emplace_back( c + nSplit0 + 1, j + nSplit1) ; else vPairs.emplace_back( c + nSplit0, j + nSplit1) ; @@ -5066,23 +5121,23 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch0 = j ; ptLastPointMatch0 = vPnt1[j] ; } - if( ! bAdvance0 && ! bAdvance1) { + if ( ! bAdvance0 && ! bAdvance1) { // sono arrivato ad un caso di incrocio!! //1. se sono vicino ad uno spigolo su entrambe le curve allora aggiungo dei rep //2. sennò accoppio comunque bool bEdgeFoundOnSecond = false ; - if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { + if ( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { // questo caso non è previsto !!!!! e non mi aspetto che avvenga - LOG_DBG_ERR( GetEGkLogger(), "During the creation of a ruled surface in mode RLT_B_MINDIST_PLUS, a not handled mismatch was found") ; + LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found") ; } - if( vEdgeSplit0[c+1]) { + if ( vEdgeSplit0[c+1]) { ++c ; ++j ; //cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist double dDist = 0 ; double dMaxDist = Dist( vPnt0[c], vMatch0[c-1].first) * 2 ; int j_temp = j ; - while( dDist < dMaxDist) { + while ( dDist < dMaxDist) { if ( vEdgeSplit1[j_temp]) { bEdgeFoundOnSecond = true ; break ; @@ -5090,7 +5145,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++j_temp ; dDist = Dist( vPnt0[c], vPnt1[j_temp]) ; } - if( bEdgeFoundOnSecond) { + if ( bEdgeFoundOnSecond) { // collego i due punti in cui ho il passaggio di un edge e tutti i punti che restano non accoppiati li metto come Rep for ( int i = 0 ; i < j_temp - j + 1 ; ++i) vPairs.emplace_back( c + nSplit0, j + i + nSplit1) ; @@ -5099,14 +5154,14 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ptLastPointMatch0 = vPnt1[j] ; } } - else if( vEdgeSplit1[j+1]) { + else if ( vEdgeSplit1[j+1]) { ++c ; ++j ; //cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist double dDist = 0 ; double dMaxDist = Dist( vPnt1[j], vMatch1[j-1].first) * 2 ; int c_temp = c ; - while( dDist < dMaxDist) { + while ( dDist < dMaxDist) { if ( vEdgeSplit0[c_temp]) { bEdgeFoundOnSecond = true ; break ; @@ -5114,9 +5169,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++c_temp ; dDist = Dist( vPnt1[j], vPnt0[c_temp]) ; } - if( bEdgeFoundOnSecond) { + if ( bEdgeFoundOnSecond) { // collego i due punti in cui ho il passaggio di un edge e tutti i punti che restano non accoppiati li metto come Rep - for( int i = 0 ; i < c_temp - c + 1 ; ++i) + for ( int i = 0 ; i < c_temp - c + 1 ; ++i) vPairs.emplace_back( c + i + nSplit0, j + nSplit1) ; c = c_temp ; dLastParamMatch1 = c - 1 ; @@ -5153,7 +5208,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nUnit = nSplit ; CrvU1.AddJoint( dSplit) ; } - if( ! vdSplit0.empty()) + if ( ! vdSplit0.empty()) nUnit = int( vdSplit0.back()) ; for ( int z = int( vdSplit0.size() - 1) ; z >= 0 ; --z) { double dSplit = vdSplit0[z] ; @@ -5173,7 +5228,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int vPairs.emplace_back( nSpanU0, nSpanU1) ; // trovo il numero di span che dovrà avere la superficie - // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) nSpanU = int(vPairs.size()) - 1 ; nSecondRowInd = nDegU * nSpanU + 1 ; @@ -5202,7 +5256,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bLast1 = true ; } const ICurveBezier* pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( nCrv0)) ; - for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + for ( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 if ( bRep0 || bLast0) @@ -5213,9 +5267,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bOk = SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd), pSubCrv0->GetControlWeight( nInd)) ; } const ICurveBezier* pSubCrv1 = GetCurveBezier( CrvU1.GetCurve( nCrv1)) ; - for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + for ( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; - // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 + // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U1 if ( bRep1 || bLast1) nInd = ! bLast1 ? 0 : nDegU ; if ( ! bRat) @@ -5226,29 +5280,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nAddedSpan ; } - //debug - ICURVEPOVECTOR vCrv ; - GetAllPatchesIsocurves( false, vCrv) ; - vector vGeo ; - for( int i = 0 ; i < int(vCrv.size()); ++i) - vGeo.push_back( vCrv[i]) ; - vector vCol( vGeo.size()) ; - fill( vCol.begin(), vCol.end(), Color( 0, 128 ,128)) ; - SaveGeoObj( vGeo, vCol, "D:/Temp/bezier/ruled/isoCurves.nge") ; - - vGeo.clear() ; - vGeo.push_back( CrvU0.Clone()) ; - vGeo.push_back( CrvU1.Clone()) ; - vCol.clear() ; - vCol.push_back( Color(0,64,128)) ; - vCol.push_back( Color(128,64,0)) ; - SaveGeoObj( vGeo, vCol, "D:/Temp/bezier/ruled/NewCurves.nge") ; - //debug - - //debug - return true ; - - return bOk ; } else if ( RLT_B_LENPAR ) { @@ -5300,7 +5331,7 @@ ParametrizeByLen( const ICurveComposite* pCurve, DBLVECTOR& vParam) DBLVECTOR vLen ; double dLenTot = 0 ; vParam.push_back( 0) ; - for( int i = 0 ; i < nSpanU ; ++i) { + for ( int i = 0 ; i < nSpanU ; ++i) { const ICurve* pSubCrv = pCurve->GetCurve( i) ; double dLen ; pSubCrv->GetLength( dLen) ; dLenTot += dLen ; @@ -5325,7 +5356,7 @@ BuildCommonParam( const DBLMATRIX& mParam, DBLVECTOR& vCommonParam) //riordino ed elimino i doppioni entro una certa tolleranza sort( vCommonParam.begin(), vCommonParam.end()) ; for ( int i = 0 ; i < int(vCommonParam.size()) - 1 ; ++i) { - for( int j = i + 1 ; j < int(vCommonParam.size()) ; ++j) { + for ( int j = i + 1 ; j < int(vCommonParam.size()) ; ++j) { if ( vCommonParam[j] - vCommonParam[i] < EPS_SMALL){ vCommonParam.erase(vCommonParam.begin() + j) ; --j ; @@ -5346,11 +5377,11 @@ SplitByCommonParam( ICURVEPOVECTOR& vCrvBezUnif, DBLVECTOR& vCommonParam, DBLMAT ICurveComposite* pCC = GetCurveComposite(vCrvBezUnif[i]) ; int c = mParam[i].size() - 1 ; DBLVECTOR vParam = mParam[i] ; - for( int j = vCommonParam.size() - 1 ; j >= 0 ; --j) { + for ( int j = vCommonParam.size() - 1 ; j >= 0 ; --j) { // capisco su quale sottocurva devo fare lo split e riconverto il parametro rispetto al numero di sottocurve while ( vCommonParam[j] < vParam[c]) --c ; - if( vCommonParam[j] - vParam[c] > EPS_SMALL) { + if ( vCommonParam[j] - vParam[c] > EPS_SMALL) { double dSplit = (vCommonParam[j] - vParam[c]) / (vParam[c+1] - vParam[c]) + c ; pCC->AddJoint( dSplit) ; vParam.insert( vParam.begin() + c + 1, vCommonParam[j]) ; @@ -5389,14 +5420,14 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDe // scorro le curve e uniformo tutte in curve di grado 3 non razionale for ( int i = 0 ; i < int( vCrvBez.size()) ; ++i) { const ICurveComposite* pCCFromSet = GetCurveComposite( vCrvBez[i]) ; - if( pCCFromSet == nullptr) + if ( pCCFromSet == nullptr) return false ; PtrOwner pCC( CreateCurveComposite()) ; - for( int j = 0 ; j < int( pCCFromSet->GetCurveCount()) ; ++j) { + for ( int j = 0 ; j < int( pCCFromSet->GetCurveCount()) ; ++j) { const ICurveBezier* pCrvBez = GetCurveBezier( pCCFromSet->GetCurve( j)) ; - if( pCrvBez == nullptr) + if ( pCrvBez == nullptr) return false ; - if( ! pCC->AddCurve( EditBezierCurve( pCrvBez, nDegU, bRat))) + if ( ! pCC->AddCurve( EditBezierCurve( pCrvBez, nDegU, bRat))) return false ; } mParam.emplace_back() ; @@ -5426,14 +5457,14 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDe vPntCtrl0.push_back( pCrvBez->GetControlPoint( 0)) ; vPntCtrl1.push_back( pCrvBez->GetControlPoint( nDegU)) ; } - if( j==0 ) + if ( j==0 ) vPntCrvs.push_back( vPntCtrl0) ; vPntCrvs.push_back( vPntCtrl1) ; } ////versione nuova //for ( int j = 0 ; j < nSpanU ; ++j ) { - // for( int z = j== 0 ? 0 : 1 ; z < nDegU + 1 ; ++z) { + // for ( int z = j== 0 ? 0 : 1 ; z < nDegU + 1 ; ++z) { // PNTVECTOR vPntCtrl ; // for ( int i = 0 ; i < int( vCrvBezUnif.size()) ; ++i) { // const ICurveComposite* pCC = GetCurveComposite( vCrvBezUnif[i]) ; @@ -5531,7 +5562,7 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDe mA.col(0) << pt0.x * pt0.x, pt1.x * pt1.x, pt2.x * pt2.x ; mA.col(1) << pt0.x, pt1.x , pt2.x ; mA.col(2) << 1, 1, 1 ; - if( abs( mA.determinant()) < EPS_SMALL) + if ( abs( mA.determinant()) < EPS_SMALL) return false ; Eigen::Vector3d b ( pt0.y, pt1.y, pt2.y) ; Eigen::Vector3d coeff = mA.fullPivLu().solve(b) ; @@ -5583,7 +5614,7 @@ bool SurfBezier::GetAllPatchesIsocurves( bool bUOrV, ICURVEPOVECTOR& vCrv) const { // restituisce tutte le isocurve di separazione tra patch in un parametro o nell'altro - if( bUOrV) { + if ( bUOrV) { for ( int v = 0 ; v < m_nSpanV ; ++v) vCrv.emplace_back( GetCurveOnU( v)) ; } @@ -5594,16 +5625,29 @@ SurfBezier::GetAllPatchesIsocurves( bool bUOrV, ICURVEPOVECTOR& vCrv) const return true ; } +struct IsoParam { + int nCrv ; + double dParam0 ; + double dParam1 ; + IsoParam( int _nCrv, double _dParam0, double _dParam1): nCrv(_nCrv), dParam0( _dParam0), dParam1( _dParam1){ } ; + bool operator < ( IsoParam& b) + { + return ( abs(dParam0 - b.dParam0) > EPS_SMALL ? dParam0 < b.dParam0 : dParam1 < b.dParam1) ; + } +}; + +typedef vector ISOPARVECT ; + //---------------------------------------------------------------------------- bool SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const ICURVEPOVECTOR& vCrv) { // converto in bezier la curva iniziale CurveComposite CrvU0 ; CrvU0.AddCurve( CurveToBezierCurve(pCurve0)) ; - if( ! CrvU0.IsValid()) + if ( ! CrvU0.IsValid()) return false ; CurveComposite CrvU1 ; CrvU1.AddCurve( CurveToBezierCurve(pCurve1)) ; - if( ! CrvU1.IsValid()) + if ( ! CrvU1.IsValid()) return false ; int nDegU = 3 ; int nDegV = 1 ; @@ -5614,93 +5658,155 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c PNTVECTOR vPnt0, vPnt1 ; Point3d pt ; CrvU0.GetStartPoint( pt) ; vPnt0.push_back( pt) ; - for( int i = 0 ; i < CrvU0.GetCurveCount() ; ++i) { + for ( int i = 0 ; i < CrvU0.GetCurveCount() ; ++i) { CrvU0.GetCurve(i)->GetEndPoint( pt) ; vPnt0.push_back( pt) ; } CrvU1.GetStartPoint( pt) ; vPnt1.push_back( pt) ; - for( int i = 0 ; i < CrvU1.GetCurveCount() ; ++i) { + for ( int i = 0 ; i < CrvU1.GetCurveCount() ; ++i) { CrvU1.GetCurve(i)->GetEndPoint( pt) ; vPnt1.push_back( pt) ; } // associo le isocurve passate in input ai relativi punti sulle due curve che generano la rigata INTINTVECTOR vPairs ; - vPairs.emplace_back( 0, 0) ; DBLVECTOR vdSplit0, vdSplit1 ; int nSplit0 = 0, nSplit1 = 0 ; Point3d ptLast0, ptLast1 ; double dLastParam0 = 0, dLastParam1 = 0 ; double dLenPrev0 = 0 ,dLenPrev1 = 0 ; + + // mi assicuro che le isocurve siano in ordine + ISOPARVECT vIso ; for ( int i = 0 ; i < ssize( vCrv) ; ++i) { - Point3d ptU0 ; vCrv[i]->GetEndPoint( ptU0) ; + Point3d ptU0 ; vCrv[i]->GetStartPoint( ptU0) ; Point3d ptU1 ; vCrv[i]->GetEndPoint( ptU1) ; double dParam0 ; CrvU0.GetParamAtPoint( ptU0, dParam0) ; double dParam1 ; CrvU1.GetParamAtPoint( ptU1, dParam1) ; + vIso.emplace_back( i, dParam0, dParam1) ; + } + sort( vIso.begin(), vIso.end()) ; + + for ( int i = 0 ; i < ssize( vIso) ; ++i) { + Point3d ptU0 ; vCrv[vIso[i].nCrv]->GetStartPoint( ptU0) ; + Point3d ptU1 ; vCrv[vIso[i].nCrv]->GetEndPoint( ptU1) ; + double& dParam0 = vIso[i].dParam0 ; + double& dParam1 = vIso[i].dParam1 ; + // se sono vicino ad un'intero allora considero il parametro intero ( uno split già esistente) + bool bIntParam0 = false ; + bool bIntParam1 = false ; + if ( abs( dParam0 - round( dParam0)) < EPS_SMALL) { + dParam0 = round( dParam0) ; + bIntParam0 = true ; + } + if ( abs( dParam1 - round( dParam1)) < EPS_SMALL) { + dParam1 = round( dParam1) ; + bIntParam1 = true ; + } int nParam0 = int( dParam0) ; int nParam1 = int( dParam1) ; int nLastParam0 = int( dLastParam0) ; int nLastParam1 = int( dLastParam1) ; - - // calcolo la parametrizzazione locale dei punti compresi tra le due isoparametriche double dLenCurr0 ; CrvU0.GetLengthAtParam( dParam0, dLenCurr0) ; - double dLen0 = dLenCurr0 - dLenPrev0 ; double dLenCurr1 ; CrvU1.GetLengthAtParam( dParam1, dLenCurr1) ; - double dLen1 = dLenCurr1 - dLenPrev1 ; - DBLVECTOR vdParamPos0, vdParamPos1 ; - int nPointsBetween0 = nParam0 - int( dLastParam0) ; - if( dParam0 - nParam0 > EPS_SMALL) - ++ nPointsBetween0 ; - for( int k = 0 ; k < nPointsBetween0 ; ++k) { - double dLen = 0 ; CrvU0.GetParamAtPoint( vPnt0[ nParam0 + 1 + k], dLen) ; - dLen -= dLenPrev0 ; - vdParamPos0.push_back( dLen) ; + int nPointsBetween0 = 0 ; + if ( dParam0 - nLastParam0 > 1) { + if ( ! bIntParam0) + nPointsBetween0 = int( dParam0 - nLastParam0) ; + else + nPointsBetween0 = int( dParam0 - nLastParam0) - 1 ; } - vdParamPos0.push_back( 1) ; - int nPointsBetween1 = nParam1 - int( dLastParam1) ; - if( dParam1 - nParam1 > EPS_SMALL) - ++ nPointsBetween1 ; - for( int k = 0 ; k < nPointsBetween1 ; ++k) { - double dLen = 0 ; CrvU1.GetParamAtPoint( vPnt1[ nParam1 + 1 + k], dLen) ; - dLen -= dLenPrev1 ; - vdParamPos1.push_back( dLen) ; + else + nPointsBetween0 = 0 ; + int nPointsBetween1 = 0 ; + if ( dParam1 - nLastParam1 > 1) { + if ( ! bIntParam1) + nPointsBetween1 = int( dParam1 - nLastParam1) ; + else + nPointsBetween1 = int( dParam1 - nLastParam1) - 1 ; } - vdParamPos1.push_back( 1) ; + else + nPointsBetween1 = 0 ; + if ( nPointsBetween0 > 0 || nPointsBetween1 > 0) { + // calcolo la parametrizzazione locale dei punti compresi tra le due isoparametriche + double dLen0 = dLenCurr0 - dLenPrev0 ; + double dLen1 = dLenCurr1 - dLenPrev1 ; + DBLVECTOR vdParamPos0 ; vdParamPos0.reserve( nPointsBetween0) ; + DBLVECTOR vdParamPos1 ; vdParamPos1.reserve( nPointsBetween1) ; + for ( int k = 0 ; k < nPointsBetween0 ; ++k) { + double dParamIntermed = 0 ; CrvU0.GetParamAtPoint( vPnt0[ nLastParam0 + 1 + k], dParamIntermed) ; + double dLen = 0 ; CrvU0.GetLengthAtParam( dParamIntermed, dLen) ; + dLen -= dLenPrev0 ; + vdParamPos0.push_back( dLen / dLen0) ; + } + vdParamPos0.push_back( 1) ; + for ( int k = 0 ; k < nPointsBetween1 ; ++k) { + double dParamIntermed = 0 ; CrvU1.GetParamAtPoint( vPnt1[ nLastParam1 + 1 + k], dParamIntermed) ; + double dLen = 0 ; CrvU1.GetLengthAtParam( dParamIntermed, dLen) ; + dLen -= dLenPrev1 ; + vdParamPos1.push_back( dLen / dLen1) ; + } + vdParamPos1.push_back( 1) ; - bool bSplitToAdd = true ; - int c0 = 0, c1 = 0 ; - while( bSplitToAdd) { - // se ho una corrispondenza tra punti allora non aggiungo split - if( abs( vdParamPos0[c0] - vdParamPos0[c1]) < EPS_PARAM) { - ++c0 ; - ++c1 ; - ++nLastParam0 ; - ++nLastParam1 ; + bool bSplitToAdd = true ; + int c0 = 0, c1 = 0 ; + while ( bSplitToAdd) { + if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) { + LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error while reparametrizing some section") ; + return false ; + } + // se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split + if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) { + ++c0 ; + ++c1 ; + ++nLastParam0 ; + ++nLastParam1 ; + vPairs.emplace_back( nLastParam0 + nSplit0, nLastParam1 + nSplit1) ; + } + // se non ho corrispondenza allora aggiungo uno split sulla curva a cui manca il punto corrispondente + else if ( vdParamPos0[c0] < vdParamPos1[c1]) { + double dPar ; CrvU1.GetParamAtLength( dLenPrev1 + dLen1 * vdParamPos0[c0], dPar) ; + if ( abs( dPar - round( dPar)) > EPS_SMALL) { + vdSplit1.push_back( dPar) ; + nSplit1 = vdSplit1.size() ; + } + else if ( dPar = round( dPar) ; dPar > nLastParam1){ + ++ nLastParam1 ; + } + ++nLastParam0 ; + vPairs.emplace_back( nLastParam0 + nSplit0, nLastParam1 + nSplit1) ; + ++c0 ; + } + else if ( vdParamPos0[c0] > vdParamPos1[c1]) { + double dPar ; CrvU0.GetParamAtLength( dLenPrev0 + dLen0 * vdParamPos1[c1], dPar) ; + // se lo split non è in prossimità di una joint già esistente allora lo aggiungo + if ( abs( dPar - round( dPar)) > EPS_SMALL) { + vdSplit0.push_back( dPar) ; + nSplit0 = vdSplit0.size() ; + } + else if ( dPar = round( dPar) ; dPar > nLastParam0){ + ++ nLastParam0 ; + } + ++nLastParam1 ; + vPairs.emplace_back( nLastParam0 + nSplit0, nLastParam1 + nSplit1) ; + ++c1 ; + } + bSplitToAdd = ! (c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ; } - // se non ho corrispondenza allora aggiungo uno split sulla curva a cui manca il punto corrispondente - else if( vdParamPos0[c0] < vdParamPos0[c1]) { - double dPar ; CrvU0.GetParamAtLength( dLenPrev0 + dLen0 * vdParamPos0[c0], dPar) ; - vdSplit1.push_back( dPar) ; - nSplit1 = vdSplit1.size() ; - ++nLastParam0 ; - vPairs.emplace_back( nLastParam0 + nSplit0, nLastParam1 + nSplit1) ; - ++c0 ; - } - else if( vdParamPos0[c0] > vdParamPos0[c1]) { - double dPar ; CrvU1.GetParamAtLength( dLenPrev1 + dLen1 * vdParamPos1[c1], dPar) ; - vdSplit0.push_back( dPar) ; - nSplit0 = vdSplit0.size() ; - ++nLastParam1 ; - vPairs.emplace_back( nLastParam0 + nSplit0, nLastParam1 + nSplit1) ; - ++c1 ; - } - bSplitToAdd = ! (c0 == ssize( vdParamPos0) && c1 == ssize( vdParamPos1)) ; } // salvo i dati di questo accoppiamento dLenPrev0 = dLenCurr0 ; dLenPrev1 = dLenCurr1 ; + if ( ! bIntParam0 && dParam0 > dLastParam0) { + vdSplit0.push_back( dParam0) ; + nSplit0 = vdSplit0.size() ; + } + if ( ! bIntParam1 && dParam1 > dLastParam1) { + vdSplit1.push_back( dParam1) ; + nSplit1 = vdSplit1.size() ; + } dLastParam0 = dParam0 ; dLastParam1 = dParam1 ; ptLast0 = ptU0 ; @@ -5708,7 +5814,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c vPairs.emplace_back( nParam0 + nSplit0, nParam1 + nSplit1) ; } - // applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep + // applico effettivamente gli split int nUnit = 0 ; if ( ! vdSplit1.empty()) nUnit = int( vdSplit1.back()) ; @@ -5723,7 +5829,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c nUnit = nSplit ; CrvU1.AddJoint( dSplit) ; } - if( ! vdSplit0.empty()) + if ( ! vdSplit0.empty()) nUnit = int( vdSplit0.back()) ; for ( int z = int( vdSplit0.size() - 1) ; z >= 0 ; --z) { double dSplit = vdSplit0[z] ; @@ -5743,7 +5849,6 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c vPairs.emplace_back( nSpanU0, nSpanU1) ; // trovo il numero di span che dovrà avere la superficie - // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) int nSpanU = int(vPairs.size()) - 1 ; int nSecondRowInd = nDegU * nSpanU + 1 ; @@ -5772,7 +5877,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c bLast1 = true ; } const ICurveBezier* pSubCrv0 = GetCurveBezier( CrvU0.GetCurve( nCrv0)) ; - for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + for ( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 if ( bRep0 || bLast0) @@ -5783,9 +5888,9 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c bOk = SetControlPoint( nAddedSpan * nDegU + i, pSubCrv0->GetControlPoint( nInd), pSubCrv0->GetControlWeight( nInd)) ; } const ICurveBezier* pSubCrv1 = GetCurveBezier( CrvU1.GetCurve( nCrv1)) ; - for( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { + for ( int i = nAddedSpan == 0 ? 0 : 1 ; i < nLastPoint ; ++ i) { int nInd = i ; - // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U0 + // se ho una ripetizione allora riaggiungo l'ultimo punto. Se sono ancora alla curva 0 invece devo aggiungere lo start della curva U1 if ( bRep1 || bLast1) nInd = ! bLast1 ? 0 : nDegU ; if ( ! bRat) diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 7f05ab0..789b8a5 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -517,9 +517,9 @@ SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const // verifico esistenza del vertice if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL) return false ; - // recupero i dati - dU = m_vVert[nId].dU ; - dV = m_vVert[nId].dV ; + // recupero i dati (verso l'esterno sempre in 0..1..2..3..) + dU = m_vVert[nId].dU / PREC_SCALE_COEFF ; + dV = m_vVert[nId].dV / PREC_SCALE_COEFF ; return true ; } diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 3aed42c..bce4122 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -41,7 +41,7 @@ using namespace std ; //---------------------------------------------------------------------------- -const double BOOLEAN_SCALE = 1024 ; +const double BOOLEAN_SCALE = PREC_SCALE_COEFF ; //---------------------------------------------------------------------------- bool diff --git a/SurfTriMeshCuts.cpp b/SurfTriMeshCuts.cpp index f6bcbec..5a106ca 100644 --- a/SurfTriMeshCuts.cpp +++ b/SurfTriMeshCuts.cpp @@ -26,7 +26,7 @@ using namespace std ; //---------------------------------------------------------------------------- -const double CUT_SCALE = 1024 ; +const double CUT_SCALE = PREC_SCALE_COEFF ; //---------------------------------------------------------------------------- bool diff --git a/SurfTriMeshOffset.cpp b/SurfTriMeshOffset.cpp index 0710ba8..dd1841a 100644 --- a/SurfTriMeshOffset.cpp +++ b/SurfTriMeshOffset.cpp @@ -9,6 +9,7 @@ // Modifiche : 10.06.25 RE Creazione modulo. // 10.06.25 RE Offset di superfici chiuse. // 04.07.25 RE Thickening Offset di superfici generiche. +// 10.12.25 RE Creazione superfici Shell. // //---------------------------------------------------------------------------- @@ -16,11 +17,17 @@ #include "stdafx.h" #include "VolZmap.h" #include "SurfTriMesh.h" -#include "EgtDev/Include/EGkDistPointSurfTm.h" -#include "\EgtDev\Include\EGkSurfTriMeshAux.h" +#include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkDistPointTria.h" +#include "/EgtDev/Include/EGkSurfTriMeshAux.h" +#include "/EgtDev/Include/EGkStmFromCurves.h" +#include "/EgtDev/Include/EGkStmFromTriangleSoup.h" +#include #define DEBUG 0 #if DEBUG + #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EGkGeoObjSave.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoVector3d.h" @@ -58,6 +65,255 @@ SumStm( const CISURFTMPVECTOR& vStm) return ( Release( pStmAdd)) ; } +//---------------------------------------------------------------------------- +// Funzioni per la distanza tra punto e superficie TriMesh in parallelo +//---------------------------------------------------------------------------- +static bool +BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff) +{ + // svuoto il risultato + vBoxDiff.clear() ; + // se box A vuoto, risultato vuoto + if ( boxA.IsEmpty()) + return false ; + // se box B vuoto o i box non si intersecano, risultato è ancora A + BBox3d boxInt ; + if ( boxB.IsSmall() || ! boxA.FindIntersection( boxB, boxInt)) { + vBoxDiff.emplace_back( boxA) ; + return true ; + } + // recupero i punti estremi dei box A e Intersezione + Point3d ptMinA, ptMaxA ; boxA.GetMinMax( ptMinA, ptMaxA) ; + Point3d ptMinInt, ptMaxInt ; boxInt.GetMinMax( ptMinInt, ptMaxInt) ; + // sotto + if ( ptMinInt.z - ptMinA.z > EPS_SMALL) { + BBox3d boxD( ptMinA, Point3d( ptMaxA.x, ptMaxA.y, ptMinInt.z)) ; + vBoxDiff.emplace_back( boxD) ; + } + // sopra + if ( ptMaxA.z - ptMaxInt.z > EPS_SMALL) { + BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMaxInt.z), ptMaxA) ; + vBoxDiff.emplace_back( boxD) ; + } + // davanti + if ( ptMinInt.y - ptMinA.y > EPS_SMALL) { + BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMinInt.z), Point3d( ptMaxA.x, ptMinInt.y, ptMaxInt.z)) ; + vBoxDiff.emplace_back( boxD) ; + } + // dietro + if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) { + BBox3d boxD( Point3d( ptMinA.x, ptMaxInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxA.y, ptMaxInt.z)) ; + vBoxDiff.emplace_back( boxD) ; + } + // sinistra + if ( ptMinInt.x - ptMinA.x > EPS_SMALL) { + BBox3d boxD( Point3d( ptMinA.x, ptMinInt.y, ptMinInt.z), Point3d( ptMinInt.x, ptMaxInt.y, ptMaxInt.z)) ; + vBoxDiff.emplace_back( boxD) ; + } + // destra + if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) { + BBox3d boxD( Point3d( ptMaxInt.x, ptMinInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxInt.y, ptMaxInt.z)) ; + vBoxDiff.emplace_back( boxD) ; + } + // risultato + return ( ! vBoxDiff.empty()) ; +} + +//---------------------------------------------------------------------------- +static bool +DistPointSurfTmMultiThread( const Point3d& ptP, const SurfTriMesh& SurfTm, double& dDist, + bool& bIsInside, INTVECTOR& vIndClosestTria) +{ + // verifico che la supercicie sia valida + if ( ! SurfTm.IsValid()) + return false ; + + // inizializzo distanza non calcolata + dDist = - 1. ; + // vettore di indici dei triangoli più vicini inizialmente vuoto + vIndClosestTria.clear() ; + // vettore dei flag temporanei inizialmente tutto a 0 + INTVECTOR vIntFlags( SurfTm.GetTriangleCount(), 0) ; + + // recupero e verifico il box locale della superficie + BBox3d b3Stm = SurfTm.GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return false ; + + // cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // termino quando non trovo più triangoli che possano soddisfare la richiesta. + Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; + double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; + double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; + double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; + // considero anche il box precedente per poter analizzare solo il volume differenza tra i due + BBox3d boxPPrev( ptP) ; + BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; + // variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima + double dMinDist = DBL_MAX ; + int nMinDistTriaIndex = SVT_NULL ; + Point3d ptMinDistPoint ; + // finché non si verifica la condizione di terminazione ingrandisco il box. + bool bContinue = true ; + + // creazione del vettore dei triangoli più vicini a ptP + vector> vTria ; // + while ( bContinue) { + // calcolo il box differenza con il precedente per non esplorare parti già considerate + BOXVECTOR vBox ; + BoundingBoxDifference( boxP, boxPPrev, vBox) ; + // Ciclo sui box differenza + bool bCollide = false ; + for ( const auto& b3Box : vBox) { + // interseco il box con quello della superficie e ne verifico la distanza minima dal punto + BBox3d b3Int ; + if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.DistFromPoint( ptP) > dMinDist) + continue ; + // ricerca sui triangoli nel box + bCollide = true ; + INTVECTOR vnIds ; + if ( SurfTm.GetAllTriaOverlapBox( b3Int, vnIds)) { + // ciclo sui triangoli del sotto-box corrente + for ( auto nT : vnIds) { + Triangle3d trCurTria ; + if ( vIntFlags[nT] == 0 && SurfTm.GetTriangle( nT, trCurTria)) { + vIntFlags[nT] = 1 ; + DistPointTriangle distPT( ptP, trCurTria) ; + double dCurrDist ; + // se la distanza del triangolo è valida e minore di quella attuale aggiorno + if ( distPT.GetDist( dCurrDist)) { + // se distanze uguali... + if ( abs( dCurrDist - dMinDist) < EPS_SMALL) + // aggiungo il triangolo + vTria.emplace_back( make_pair( nT, trCurTria)) ; + // se minore... + else if ( dCurrDist < dMinDist) { + // pulisco il vettore + vTria.clear() ; + dMinDist = dCurrDist ; + nMinDistTriaIndex = nT ; + distPT.GetMinDistPoint( ptMinDistPoint) ; + // aggiungo il triangolo + vTria.emplace_back( make_pair( nT, trCurTria)) ; + } + } + } + } + } + } + // se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box + if ( ! bCollide || dMinDist < EPS_SMALL) + bContinue = false ; + else { + boxPPrev = boxP ; + boxP.Expand( dDeltaLen) ; + } + } + // se non ho trovato nessun triangolo, errore + if ( nMinDistTriaIndex == SVT_NULL) + return false ; + + // riempio il vettore dei triangoli a minima distanza + for ( auto& Tria : vTria) + vIndClosestTria.emplace_back( Tria.first) ; + // salvo la distanza + dDist = dMinDist ; + + // determino il Side + if ( dDist < EPS_SMALL) { + bIsInside = false ; + return true ; + } + // se ho solo un triangolo + else if ( int( vTria.size()) == 1) { + bIsInside = ( ( ptP - ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ; + return true ; + } + + // controllo se tutti i triangoli a minima distanza forniscono la stessa informazione + // ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito ) + bool bInside = false ; + bool bOutside = false ; + for ( int i = 0 ; i < int( vTria.size()) ; ++ i) { + if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL) + bInside = true ; + else + bOutside = true ; + } + + bIsInside = false ; + if ( bOutside == bInside) { + Point3d ptBar_tot ; + for ( const auto& Tria : vTria) + ptBar_tot += Tria.second.GetCentroid() ; + for ( const auto& Tria : vTria) { + Point3d ptInters1, ptInters2 ; + int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ; + if ( nType == ILTT_IN) { + DistPointTriangle( ptP, Tria.second).GetMinDistPoint( ptMinDistPoint) ; + bIsInside = ( ( ptP - ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ; + nMinDistTriaIndex = Tria.first ; + break ; + } + } + } + else + bIsInside = bInside ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ClassifyTrianglesMultiThread( const TRIA3DEXVECTOR& vTria, int nIndS, int nIndE, + const SurfTriMesh& SurfTm, double dOffs, double dPrec, + bool bSaveInside, BOOLVECTOR& vbSafe) +{ + // verifico che la superficie sia valida + if ( ! SurfTm.IsValid()) + return false ; + // verifico la validità degli indici + if ( nIndS < 0 || nIndE >= int( vTria.size())) + return false ; + // verifico la dimensione dei vettori + if ( vTria.size() != vbSafe.size()) + return false ; + + // scorro gli indici dei triangoli da classificare + for ( int k = nIndS ; k <= nIndE ; ++ k) { + // recupero il triangolo corrente + const Triangle3dEx& Tria = vTria[k] ; + // preparo gli elementi di classificazione + DBLVECTOR vDists ; vDists.resize( 3) ; + INTMATRIX matIndClosestTria ; matIndClosestTria.resize( 3) ; + // verifico che i suoi punti siano distanti almeno |dOffs| - dTol dalla superficie + vbSafe[k] = true ; + for ( int i = 0 ; vbSafe[k] && i < 3 ; ++ i) { + bool bIsInside = false ; + DistPointSurfTmMultiThread( Tria.GetP( i), SurfTm, vDists[i], bIsInside, matIndClosestTria[i]) ; + vbSafe[k] = ( ( vDists[i] > abs( dOffs) - 0.25 * dPrec) && + ( vDists[i] < abs( dOffs) + 0.25 * dPrec) && + ( bIsInside == bSaveInside)) ; + } + // se tutti sufficientemente distanti + if ( vbSafe[k]) { + // i triangoli a minima distanza devono avere normale simile + bool bPerp = true ; + for ( int i = 0 ; bPerp && i < 3 ; ++ i) { + for ( int j = 0 ; bPerp && j < int( matIndClosestTria[i].size()) ; ++ j) { + Triangle3d TriaCloser ; + SurfTm.GetTriangle( matIndClosestTria[i][j], TriaCloser) ; + bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < cos( 30. * DEGTORAD)) ; + } + } + vbSafe[k] = ( ! bPerp) ; + } + } + + return true ; +} + //---------------------------------------------------------------------------- // Funzione che crea l'Offset di una superficie TriMesh //---------------------------------------------------------------------------- @@ -94,123 +350,138 @@ CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPr return SumStm( vStm) ; // creo lo Zmap associato alle superfici TriMesh - VolZmap OneVolZmap ; - if ( ! OneVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType)) + VolZmap myVolZmap ; + if ( ! myVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType)) return nullptr ; - if ( ! OneVolZmap.IsValid()) + if ( ! myVolZmap.IsValid()) return nullptr ; // recupero le superfici aperte CISURFTMPVECTOR vStmOpen ; for ( const ISurfTriMesh* pStm : vStm) { - if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed()) + if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed()) vStmOpen.emplace_back( pStm) ; } // --- se non ho superfici aperte if ( vStmOpen.empty()) { // restituisco la superficie TriMesh di Offset - return ( OneVolZmap.GetSurfTriMesh()) ; + return ( myVolZmap.GetSurfTriMesh()) ; } - // --- se ho delle superfici aperte - // lo Zmap creato è orientato e definisce una superficie chiusa; devo rimuovere i triangoli in eccesso - - // anzitutto controllo che lo Zmap sia valido - if ( ! OneVolZmap.IsValid()) - return nullptr ; - - // inzializzo la superficie TriMesh da restituire - PtrOwner pStm( CreateBasicSurfTriMesh()) ; - if ( IsNull( pStm) || ! pStm->Init( 3, 1)) - return nullptr ; - PointGrid3d VertGrid ; VertGrid.Init( 50000) ; - - // tolleranza di vicinanza alla superficie - double dTolDist = 30. * EPS_SMALL ; - - #if DEBUG - VT.emplace_back( OneVolZmap.Clone()) ; - VC.emplace_back( BLACK) ; - #endif - - // ciclo lungo i blocchi dello ZMap - for ( int nB = 0 ; nB < OneVolZmap.GetBlockCount() ; ++ nB) { - - // recupero i triangoli + // --- se ho delle superfici chiuse + TRIA3DEXVECTOR vAllTria, vTriaOffs ; + for ( int nB = 0 ; nB < myVolZmap.GetBlockCount() ; ++ nB) { TRIA3DEXVECTOR vTria, vTriaSafe ; - OneVolZmap.GetBlockTriangles( nB, vTria) ; - - // un triangolo viene ritenuto valido se è non è troppo vicino ( dOffs) alle superfici aperte + myVolZmap.GetBlockTriangles( nB, vTria) ; + #if DEBUG + TRIA3DVECTOR vTriaUnsafe ; + #endif for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) { - - // recupero il triangolo Triangle3dEx& Tria = vTria[nT] ; - - // scorro le superficie aperte - bool bInsert = true ; - for ( int nS = 0 ; bInsert && nS < int( vStm.size()) ; ++ nS) { - - // controllo se posso inserirlo - vector vDistPtStm ; - for ( int i = 0 ; i < 3 && bInsert ; ++ i) { - double dDist = 0. ; - vDistPtStm.emplace_back( DistPointSurfTm( Tria.GetP( i), *vStm[nS])) ; - bInsert = ( vDistPtStm.back().GetDist( dDist) && dDist > abs( dOffs) - dTolDist) ; - } - // se il triangolo è al più a distanza di |dOffs| - dTolDist - if ( bInsert) { - // recupero i triangoli a distanza minima dai vertici del triangolo corrente - bool bPerp = true ; - for ( int i = 0 ; i < 3 && bPerp ; ++ i) { - INTVECTOR vTria ; - vDistPtStm[i].GetMinDistTriaIndices( vTria) ; - for ( int j = 0 ; j < int( vTria.size()) && bPerp ; ++ j) { - Triangle3d TriaCloser ; - vStm[nS]->GetTriangle( vTria[j], TriaCloser) ; - bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < dTolDist) ; - } - } - // se tutti i triangoli a distanza minima sono perpendicolari, allora non lo inserisco - bInsert = ( ! bPerp) ; + BBox3d BBoxTria ; + Tria.GetLocalBBox( BBoxTria) ; + // azzero flag di colore + vAllTria.push_back( Tria) ; + } + } + // classifico i triangoli + PtrOwner pStmBasic( nullptr) ; + if ( int( vStmOpen.size() == 1)) + pStmBasic.Set( GetBasicSurfTriMesh( CloneSurfTriMesh( vStmOpen[0]))) ; + else { + StmFromTriangleSoup AllOpenStmSoup ; AllOpenStmSoup.Start() ; + for ( const ISurfTriMesh* pStmOpen : vStmOpen) { + if ( pStmOpen != nullptr && pStmOpen->IsValid()) { + for ( int nT = 0 ; nT < pStmOpen->GetTriangleCount() ; ++ nT) { + Triangle3d Tria ; + if ( pStmOpen->GetTriangle( nT, Tria)) + AllOpenStmSoup.AddTriangle( Tria) ; } } - - // se triangolo da inserire - if ( bInsert) - vTriaSafe.emplace_back( Tria) ; - - #if DEBUG - ICurveComposite* pCompo = CreateCurveComposite() ; - pCompo->AddPoint( Tria.GetP( 0)) ; - pCompo->AddLine( Tria.GetP( 1)) ; - pCompo->AddLine( Tria.GetP( 2)) ; - pCompo->Close() ; - Color myCol = ( bInsert ? Color( 0., 1., 0., .5) : Color( 1., 0., 0., .5)) ; - VT.emplace_back( CloneCurveComposite( pCompo)) ; - VC.emplace_back( myCol) ; - ISurfFlatRegion* pSfrTria = CreateSurfFlatRegion() ; - pSfrTria->AddExtLoop( pCompo) ; - VT.emplace_back( pSfrTria) ; - VC.emplace_back( myCol) ; - #endif } - - // inserisco tutti i triangoli validi - if ( ! pStm->AddTriaFromZMap( vTriaSafe, VertGrid)) - return nullptr ; + AllOpenStmSoup.End() ; + pStmBasic.Set( GetBasicSurfTriMesh( AllOpenStmSoup.GetSurf())) ; + } + if ( pStmBasic == nullptr) + return nullptr ; + BBox3d b3Stm = pStmBasic->GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return nullptr ; + // numero di triangoli da analizzare + int nTriaCnt = int( vAllTria.size()) ; + // definisco un vettore di Flag per i triangoli già visitati + INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ; + // numero massimo di thread concorrenti + int nThreadMax = thread::hardware_concurrency() ; + bool bOk = true ; + BOOLVECTOR vbSafeTria( vAllTria.size(), true) ; + if ( nThreadMax <= 1 || nTriaCnt < 50) + ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, abs( dOffs), dPrec, ( dOffs < 0.), vbSafeTria) ; + else { + const int MAX_PARTS = 32 ; + INTINTVECTOR vFstLst( MAX_PARTS) ; + // calcolo le parti del vettore + int nPartCnt = min( nThreadMax, MAX_PARTS) ; + int nPartDim = nTriaCnt / nPartCnt + 1 ; + for ( int i = 0 ; i < nPartCnt ; ++ i) { + vFstLst[i].first = i * nPartDim ; + vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ; + } + // processo le parti + future vRes[MAX_PARTS] ; + for ( int i = 0 ; i < nPartCnt ; ++ i) { + vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first, + vFstLst[i].second, cref( *pStmBasic), abs( dOffs), dPrec, ( dOffs < 0.), ref( vbSafeTria)) ; + } + // attendo i risultati + int nFin = 0 ; + while ( nFin < nPartCnt) { + for ( int i = 0 ; i < nPartCnt ; ++ i) { + if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) { + bOk = vRes[i].get() && bOk ; + ++ nFin ; + } + } + } + } + if ( ! bOk) + return nullptr ; + TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ; + #if DEBUG + TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ; + #endif + for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) { + if ( vbSafeTria[i]) + vTriaSafe.emplace_back( vAllTria[i]) ; + #if DEBUG + if ( ! vbSafeTria[i]) + vTriaUnSafe.emplace_back( vAllTria[i]) ; + #endif } + // definisco la superficie con i soli triangoli validi + StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ; + for ( const Triangle3d& SafeTria : vTriaSafe) + TriaSoup.AddTriangle( SafeTria) ; + TriaSoup.End() ; + PtrOwner pStmOffs( TriaSoup.GetSurf()) ; + if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0) + return nullptr ; + #if DEBUG + StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ; + for ( const Triangle3d& _unsafeTria : vTriaUnSafe) + _invalidSoup.AddTriangle( _unsafeTria) ; + _invalidSoup.End() ; + VT.emplace_back( pStmOffs->Clone()) ; + VC.emplace_back( LIME) ; + VT.emplace_back( _invalidSoup.GetSurf()) ; + VC.emplace_back( RED) ; SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ; #endif - - // sistemo la topologia - if ( ! pStm->AdjustTopologyFromZMap()) - return nullptr ; - - return ( Release( pStm)) ; + return ( Release( pStmOffs)) ; } //---------------------------------------------------------------------------- @@ -240,3 +511,280 @@ CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, // restituisco la superficie TriMesh return ( OneVolZmap.GetSurfTriMesh()) ; } + +//---------------------------------------------------------------------------- +// Funzione per creare la Superficie TriMesh Shell da una Trimesh aperta +//---------------------------------------------------------------------------- +ISurfTriMesh* +CreateSurfTriMeshShell( const ISurfTriMesh* pStm, double dThick, double dPrec) +{ + // verifico che la superficie sia valida ed aperta + if ( pStm == nullptr || ! pStm->IsValid() || pStm->IsClosed()) + return nullptr ; + // lo spessore deve essere sempre positivo, il verso è sempre dato dalla normale dei triangoli + dThick = - max( 10. * EPS_SMALL, abs( dThick)) ; + + // creo il suo Offset ( salvandomi lo Zmap per l'orientamento) + #if DEBUG + PerformanceCounter PC ; PC.Start() ; + #endif + VolZmap myVolZMap ; + if ( ! myVolZMap.CreateFromTriMeshOffset( { pStm}, dThick, dPrec)) + return nullptr ; + if ( ! myVolZMap.IsValid()) + return nullptr ; + #if DEBUG + LOG_INFO( GetEGkLogger(), ( string{ "Tria Time : "} + ToString( PC.Stop())).c_str()) ; + VT.clear() ; VC.clear() ; + VT.emplace_back( myVolZMap.Clone()) ; + VC.emplace_back( BLACK) ; + VT.emplace_back( pStm->Clone()) ; + VC.emplace_back( YELLOW) ; + SaveGeoObj( VT, VC, "C:\\Temp\\VolZMapOffs.nge") ; + #endif + + #if DEBUG + VT.clear() ; VC.clear() ; + PC.Start() ; + #endif + + // recupero i triangoli dallo ZMap creato + TRIA3DEXVECTOR vAllTria, vTriaOffs ; + for ( int nB = 0 ; nB < myVolZMap.GetBlockCount() ; ++ nB) { + TRIA3DEXVECTOR vTria, vTriaSafe ; + myVolZMap.GetBlockTriangles( nB, vTria) ; + #if DEBUG + TRIA3DVECTOR vTriaUnsafe ; + #endif + for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) { + Triangle3dEx& Tria = vTria[nT] ; + BBox3d BBoxTria ; + Tria.GetLocalBBox( BBoxTria) ; + // azzero flag di colore + vAllTria.push_back( Tria) ; + } + } + // classifico i triangoli + const SurfTriMesh* pStmBasic = GetBasicSurfTriMesh( pStm) ; + if ( pStmBasic == nullptr) + return nullptr ; + BBox3d b3Stm = pStmBasic->GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return nullptr ; + // numero di triangoli da analizzare + int nTriaCnt = int( vAllTria.size()) ; + // definisco un vettore di Flag per i triangoli già visitati + INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ; + // numero massimo di thread concorrenti + int nThreadMax = thread::hardware_concurrency() ; + bool bOk = true ; + BOOLVECTOR vbSafeTria( vAllTria.size(), true) ; + if ( nThreadMax <= 1 || nTriaCnt < 50) + ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, dThick, dPrec, true, vbSafeTria) ; + else { + const int MAX_PARTS = 32 ; + INTINTVECTOR vFstLst( MAX_PARTS) ; + // calcolo le parti del vettore + int nPartCnt = min( nThreadMax, MAX_PARTS) ; + int nPartDim = nTriaCnt / nPartCnt + 1 ; + for ( int i = 0 ; i < nPartCnt ; ++ i) { + vFstLst[i].first = i * nPartDim ; + vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ; + } + // processo le parti + future vRes[MAX_PARTS] ; + for ( int i = 0 ; i < nPartCnt ; ++ i) { + vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first, + vFstLst[i].second, cref( *pStmBasic), dThick, dPrec, true, ref( vbSafeTria)) ; + } + // attendo i risultati + int nFin = 0 ; + while ( nFin < nPartCnt) { + for ( int i = 0 ; i < nPartCnt ; ++ i) { + if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) { + bOk = vRes[i].get() && bOk ; + ++ nFin ; + } + } + } + } + if ( ! bOk) + return nullptr ; + TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ; + #if DEBUG + TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ; + #endif + for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) { + if ( vbSafeTria[i]) + vTriaSafe.emplace_back( vAllTria[i]) ; + #if DEBUG + if ( ! vbSafeTria[i]) + vTriaUnSafe.emplace_back( vAllTria[i]) ; + #endif + } + + // definisco la superficie con i soli triangoli validi + StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ; + for ( const Triangle3d& SafeTria : vTriaSafe) + TriaSoup.AddTriangle( SafeTria) ; + TriaSoup.End() ; + PtrOwner pStmOffs( TriaSoup.GetSurf()) ; + if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0) + return nullptr ; + + #if DEBUG + LOG_INFO( GetEGkLogger(), ( string{ "Tria Time ( exceed Approx) : "} + ToString( PC.Stop())).c_str()) ; + StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ; + for ( const Triangle3d& _unsafeTria : vTriaUnSafe) + _invalidSoup.AddTriangle( _unsafeTria) ; + _invalidSoup.End() ; + VT.emplace_back( pStmOffs->Clone()) ; + VC.emplace_back( LIME) ; + VT.emplace_back( _invalidSoup.GetSurf()) ; + VC.emplace_back( RED) ; + SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ; + VT.clear() ; VC.clear() ; + PC.Start() ; + #endif + + // recupero i loops della superficie originaria e del suo Offset orientato ( non devono essere diminuiti) + POLYLINEVECTOR vPL, vPLOffs ; + if ( ! pStm->GetLoops( vPL) || ! pStmOffs->GetLoops( vPLOffs)) + return nullptr ; + + // trasformo ogni loop in curve composite ( devono essere chiuse) + ICRVCOMPOPOVECTOR vCompoLoops ; vCompoLoops.reserve( vPL.size()) ; + for ( const PolyLine& PL : vPL) { + if ( PL.IsClosed()) { + if ( ! vCompoLoops.emplace_back( CreateCurveComposite()) || + ! vCompoLoops.back()->FromPolyLine( PL) || + ! vCompoLoops.back()->IsValid()) + return nullptr ; + } + } + ICRVCOMPOPOVECTOR vCompoOffsLoops ; vCompoOffsLoops.reserve( vPLOffs.size()) ; + for ( const PolyLine& PLOffs : vPLOffs) { + if ( PLOffs.IsClosed()) { + if ( ! vCompoOffsLoops.emplace_back( CreateCurveComposite()) || + ! vCompoOffsLoops.back()->FromPolyLine( PLOffs) || + ! vCompoOffsLoops.back()->IsValid()) + return nullptr ; + } + } + + #if DEBUG + VT.emplace_back( pStmOffs->Clone()) ; + VC.emplace_back( YELLOW) ; + for ( ICurveComposite* pCompo : vCompoLoops) { + VT.emplace_back( pCompo->Clone()) ; + VC.emplace_back( AQUA) ; + } + for ( ICurveComposite* pCompoOffs : vCompoOffsLoops) { + VT.emplace_back( pCompoOffs->Clone()) ; + VC.emplace_back( ORANGE) ; + } + SaveGeoObj( VT, VC, "C:\\Temp\\myCurve.nge") ; + VT.clear() ; VC.clear() ; + #endif + + // per ogni curva della superficie originale cerco la sua associata + // NB. per la creazione della superficie ruled la prima curva è quellla che determina il verso + // dei triangoli associati. Per un corretto ed automatico orientamento della superficie + // la prima curva deve essere sempre definita dalla superficie originale ed invertita ( le + // curve nella rigata devono seguire lo stesso orientamento + ISURFTMPOVECTOR vStmRuled ; vStmRuled.reserve( vCompoLoops.size()) ; + BOOLVECTOR vIndMatched( vCompoOffsLoops.size(), false) ; + for ( ICurveComposite* pCompoLoop : vCompoLoops) { + // sposto il punto iniziale della curva nel tratto più lungo + double dMaxLen = - INFINITO ; + int nIndCrv = 0 ; + for ( int nCrv = 0 ; nCrv < pCompoLoop->GetCurveCount() ; ++ nCrv) { + const ICurve* pCurve = pCompoLoop->GetCurve( nCrv) ; + if ( pCurve != nullptr && pCurve->IsValid()) { + double dCurrLen = 0. ; + pCurve->GetLength( dCurrLen) ; + if ( dCurrLen > dMaxLen) { + dMaxLen = dCurrLen ; + nIndCrv = nCrv ; + } + } + } + pCompoLoop->ChangeStartPoint( nIndCrv + 0.5) ; + Point3d ptStart ; pCompoLoop->GetStartPoint( ptStart) ; + // dalle altre curve derivanti dalla superficie di Offset cerco quella più vicina al punto inziale + double dMinSqDist = INFINITO ; + int nIndOffsCrv = -1 ; + Point3d ptMinDist ; + for ( int nOffsCrv = 0 ; nOffsCrv < int( vCompoOffsLoops.size()) ; ++ nOffsCrv) { + if ( vIndMatched[nOffsCrv]) + continue ; + // recupero la curva e calcolo la distanza + const ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nOffsCrv] ; + int nFlag = 0 ; + Point3d ptCurrMinDist ; + if ( DistPointCurve( ptStart, *pCompoOffsLoop).GetMinDistPoint( 0., ptCurrMinDist, nFlag)) { + double dCurrSqDist = SqDist( ptStart, ptCurrMinDist) ; + if ( dCurrSqDist < dMinSqDist) { + dMinSqDist = dCurrSqDist ; + nIndOffsCrv = nOffsCrv ; + ptMinDist = ptCurrMinDist ; + } + } + } + if ( nIndOffsCrv == -1) + return nullptr ; + // associo le due curve + ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nIndOffsCrv] ; + double dParMinDist = 0. ; + pCompoOffsLoop->GetParamAtPoint( ptMinDist, dParMinDist, 10. * EPS_SMALL) ; + pCompoOffsLoop->ChangeStartPoint( dParMinDist) ; + + #if DEBUG + Color _cCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; + VT.emplace_back( pCompoLoop->Clone()) ; + VC.emplace_back( _cCol) ; + VT.emplace_back( pCompoOffsLoop->Clone()) ; + VC.emplace_back( _cCol) ; + #endif + + // creo la superficie tra queste due curve e la oriento in modo da definire un volume + pCompoLoop->Invert() ; + PtrOwner pStmRuled( GetSurfTriMeshRuled( pCompoLoop, pCompoOffsLoop, ISurfTriMesh::RuledType::RLT_MINDIST)) ; + if ( IsNull( pStmRuled) || ! pStmRuled->IsValid() || + ! vStmRuled.emplace_back( Release( pStmRuled))) + return nullptr ; + + #if DEBUG + LOG_INFO( GetEGkLogger(), ( string{ "Strip generation : "} + ToString( PC.Stop())).c_str()) ; + VT.emplace_back( vStmRuled.back()->Clone()) ; + VC.emplace_back( _cCol) ; + _cCol.SetAlpha( .5) ; + #endif + } + + #if DEBUG + SaveGeoObj( VT, VC, "C:\\Temp\\Strips.nge") ; + PC.Start() ; + #endif + + // compongo la superficie finale + PtrOwner pStmOrig( CloneSurfTriMesh( pStm)) ; + if ( IsNull( pStmOrig) || ! pStmOrig->IsValid()) + return nullptr ; + PtrOwner pStmRef( Release( pStmOrig)) ; + if ( IsNull( pStmRef) || ! pStmRef->IsValid()) + return nullptr ; + for ( int nStrip = 0 ; nStrip < int( vStmRuled.size()) ; ++ nStrip) { + if ( ! pStmRef->DoSewing( *vStmRuled[nStrip])) + return nullptr ; + } + if ( ! pStmRef->DoSewing( *pStmOffs)) + return nullptr ; + pStmRef->Repair() ; + + #if DEBUG + LOG_INFO( GetEGkLogger(), ( string{ "Sewing : "} + ToString( PC.Stop())).c_str()) ; + #endif + + return ( ( ! IsNull( pStmRef) && pStmRef->IsValid()) ? Release( pStmRef) : nullptr) ; +} \ No newline at end of file diff --git a/Tree.cpp b/Tree.cpp index 86df55b..b4a318a 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -455,11 +455,46 @@ Tree::Split( int nId, double dSplitValue) { Cell& cToSplit = m_mTree.at(nId) ; // controllo che lo split non venga fatto sul lato della cella - if ( ( cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().x + EPS_SMALL && - dSplitValue < cToSplit.GetTopRight().x - EPS_SMALL) || - ( ! cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().y + EPS_SMALL && - dSplitValue < cToSplit.GetTopRight().y - EPS_SMALL)) { - // quando si implementerà lo split a parametro libero bisognerà impedire che si facciano split troppo vicini al bordo della cella!!!!!!!!!!!!!!!!!!! + bool bGoodSplitVert = cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().x + 10 * EPS_SMALL && + dSplitValue < cToSplit.GetTopRight().x - 10 * EPS_SMALL ; + bool bGoodSplitHoriz = ! cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().y + 10 * EPS_SMALL && + dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ; + Point3d ptP00, ptP01, ptP10, ptP11 ; + + if( bGoodSplitVert) { + if( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) { + GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; + GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ; + GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; + GetPoint( dSplitValue, cToSplit.GetTopRight().y, ptP11) ; + } + else { + GetPoint( dSplitValue, cToSplit.GetBottomLeft().y, ptP00) ; + GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ; + GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ; + GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; + } + if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) + bGoodSplitVert = false ; + } + if( bGoodSplitHoriz) { + if( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) { + GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; + GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ; + GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ; + GetPoint( cToSplit.GetTopRight().x, dSplitValue, ptP11) ; + } + else { + GetPoint( cToSplit.GetBottomLeft().x, dSplitValue, ptP00) ; + GetPoint( cToSplit.GetBottomRight().x, dSplitValue, ptP10) ; + GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; + GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; + } + if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) + bGoodSplitHoriz = false ; + } + + if ( bGoodSplitVert || bGoodSplitHoriz) { cToSplit.m_dSplit = dSplitValue ; Cell cChild1, cChild2 ; cChild1.m_nDepth = cToSplit.m_nDepth + 1 ; @@ -728,13 +763,13 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) // ( dSideMinVal è zero se entrambi i lati da splittare sono collassati in un punto, controllo dLengMinVal) bool bSplit = false ; bool bParamDimOk = false ; - if( bVert) + if ( bVert) bParamDimOk = ( pcToSplit->GetTopRight().x - pcToSplit->GetBottomLeft().x) / 2 > 100 * EPS_PARAM ; else bParamDimOk = ( pcToSplit->GetTopRight().y - pcToSplit->GetBottomLeft().y) / 2 > 100 * EPS_PARAM ; bool bDimOk = ( dSideMinVal / 2 >= dSideMin || ( dSideMinVal < EPS_SMALL && dLengMinVal / 2 >= dSideMin)) && bParamDimOk ; if ( dSideMaxVal > dSideMax) { - bSplit = true ; + bSplit = true ; //LOG_DBG_INFO( GetEGkLogger(), " Split by SideMax") } else if ( dSagV > dLinTol || dSagU > dLinTol) { @@ -746,18 +781,19 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) if ( bSplit) { pcToSplit->SetSplitDirVert( bVert) ; // effettuo lo split - Split( nCToSplit) ; - // procedo con lo split del Child1 - nCToSplit = pcToSplit->m_nChild1 ; - pcToSplit = &m_mTree[nCToSplit] ; + if ( Split( nCToSplit)) { + // procedo con lo split del Child1 + nCToSplit = pcToSplit->m_nChild1 ; + pcToSplit = &m_mTree[nCToSplit] ; + } } else { // sono arrivato ad una cella Leaf, quindi salvo la cella m_vnLeaves.push_back( nCToSplit) ; pcToSplit->SetProcessed() ; - if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) + if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) pcToSplit->m_nCollapsed = Cell::Collapsed::VERT_EDGES ; - else if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) + else if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) pcToSplit->m_nCollapsed = Cell::Collapsed::HORIZ_EDGES ; else pcToSplit->m_nCollapsed = Cell::Collapsed::NO_COLLAPSE ; @@ -858,22 +894,23 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) { pcToSplit->SetSplitDirVert( bVert) ; // effettuo lo split - Split( nCToSplit) ; - - // procedo con lo split del Child1 - nCToSplit = pcToSplit->m_nChild1 ; - pcToSplit = &m_mTree[nCToSplit] ; + if ( Split( nCToSplit)){ + // procedo con lo split del Child1 + nCToSplit = pcToSplit->m_nChild1 ; + pcToSplit = &m_mTree[nCToSplit] ; + } } else { // sono arrivato ad una cella Leaf, quindi salvo la cella - m_vnLeaves.push_back( nCToSplit) ; pcToSplit->SetProcessed() ; - if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) + if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) pcToSplit->m_nCollapsed = Cell::Collapsed::VERT_EDGES ; - else if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) + else if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) pcToSplit->m_nCollapsed = Cell::Collapsed::HORIZ_EDGES ; - else + else { pcToSplit->m_nCollapsed = Cell::Collapsed::NO_COLLAPSE ; + m_vnLeaves.push_back( nCToSplit) ; + } // risalgo i parent finché non trovo il primo Child2 da processare nCToSplit = pcToSplit->m_nParent ; @@ -1473,7 +1510,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon int c = 0 ; for ( int nId : m_vnLeaves) { Cell& cell = m_mTree.at( nId) ; - if( cell.m_nCollapsed != Cell::Collapsed::NO_COLLAPSE) + if ( cell.m_nCollapsed != Cell::Collapsed::NO_COLLAPSE) continue ; vVertices.clear() ; vVertices3d.clear() ; @@ -1486,7 +1523,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon std::fill( vbBonusVert.begin(), vbBonusVert.end(), false) ; vnVert.push_back( int(vVertices.size()) - 1) ; GetBottomNeigh( nId, vNeigh) ; - if( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::VERT_EDGES) + if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::VERT_EDGES) GetBottomNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().x, cell.GetTopRight().x)) ; Point3d ptP00, ptP10, ptP11, ptP01 ; GetPoint( cell.GetBottomLeft().x, cell.GetBottomLeft().y, ptP00) ; @@ -1522,7 +1559,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon bBottomRight = false ; vNeigh.clear() ; GetRightNeigh ( nId, vNeigh) ; - if( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::HORIZ_EDGES) + if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::HORIZ_EDGES) GetRightNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().y, cell.GetTopRight().y)) ; // aggiungo i vertici che sono sul lato right, solo se ho più di un vicino right if ( vNeigh.size() > 1){ @@ -1564,7 +1601,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.push_back( pt3d) ; vnVert.push_back( int(vVertices.size()) - 1) ; GetTopNeigh ( nId, vNeigh) ; - if( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::VERT_EDGES) + if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::VERT_EDGES) GetTopNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().x, cell.GetTopRight().x)) ; std::reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top @@ -1596,7 +1633,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon bTopLeft = false ; vNeigh.clear() ; GetLeftNeigh ( nId, vNeigh) ; - if( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::HORIZ_EDGES) + if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::HORIZ_EDGES) GetLeftNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().y, cell.GetTopRight().y)) ; std::reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left @@ -1679,7 +1716,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon bAlreadyCropped = true ; } if ( AreSamePointApprox(ptP10, ptP11)) { - if( bAlreadyCropped) + if ( bAlreadyCropped) continue ; // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] && ! vbBonusVert[2]){ // lati contati a partire da quello sopra in senso CCW @@ -1707,7 +1744,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon bAlreadyCropped = true ; } if ( AreSamePointApprox(ptP11, ptP01)) { - if( bAlreadyCropped) + if ( bAlreadyCropped) continue ; // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] && ! vbBonusVert[3]){ // lati contati a partire da quello sopra in senso CCW @@ -1735,7 +1772,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon bAlreadyCropped = true ; } if ( AreSamePointApprox(ptP01, ptP00)) { - if( bAlreadyCropped) + if ( bAlreadyCropped) continue ; // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] && ! vbBonusVert[2]) { // lati contati a partire da quello sopra in senso CCW @@ -1801,10 +1838,10 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon int nVertCorr = int(vVerticesCorr.size()); for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { int dPar = i ; - if( ! vbKeepPoint[i]) + if ( ! vbKeepPoint[i]) dPar = -1 ; vPolygonsBasic.back().AddUPoint( dPar, vVertices.at( i)) ; - if( i < nVertCorr){ + if ( i < nVertCorr){ vPolygonsCorrected.back().AddUPoint( dPar, vVerticesCorr.at( i)) ; vPolygons3d.back().AddUPoint( dPar, vVertices3d.at( i)) ; } @@ -2000,7 +2037,7 @@ Tree::UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt) } bAdded = true ; } - if( pCC->IsValid()) { + if ( pCC->IsValid()) { if ( ! bAdded) pCC->AddLine( pt) ; Vector3d vtDir = pt - ptLast ; @@ -2131,7 +2168,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) UpdateSplitLoop( pCCLoopSplit, vptInters.back()) ; } // controllo di aggiungere un punto abbastanza distante dal precedente - if( ! AreSamePointXYEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) { + if ( ! AreSamePointXYEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) { // aggiungo la fine del segmento nel vettore delle intersezioni vptInters.push_back( ptCurr) ; // aggiorno la compo splittata @@ -2370,7 +2407,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, if ( icc.GetOverlaps()) { for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) { icc.GetIntCrvCrvInfo( i, iccInfo) ; - if( iccInfo.bOverlap){ + if ( iccInfo.bOverlap){ ptInters = iccInfo.IciA[1].ptI ; break ; } @@ -2378,14 +2415,14 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, } else { int nLastInters = icc.GetIntersCount() -1 ; - if( nLastInters < 0) + if ( nLastInters < 0) return false ; icc.GetIntCrvCrvInfo( nLastInters, iccInfo) ; ptInters = iccInfo.IciA[0].ptI ; } // determino il lato/vertice di uscita - if( ! OnWhichEdge( nId, ptInters, nEdge)) + if ( ! OnWhichEdge( nId, ptInters, nEdge)) return false ; pCell->m_vInters.back().nOut = nEdge ; // se è risultato che sono abbastanza vicino( di EPS_SMALL) ad un vertice allora il punto aggiunto sarà il vertice vero e proprio @@ -2746,10 +2783,10 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, //---------------------------------------------------------------------------- bool -Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, - const PolyLine& plCell, const PolyLine& plCell3d) +Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, + INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) { - // conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato + // conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato int nId = m_vnLeaves[nLeafId] ; Cell& cCell = m_mTree[nId] ; PNTMATRIX vEdgeVertex(4) ; @@ -2759,38 +2796,36 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX Point3d ptTl = cCell.GetTopLeft() ; Point3d ptBr = cCell.GetBottomRight() ; int nVertToErase = m_mTree.at(nId).m_nVertToErase ; - if( nVertToErase != 2) + if ( nVertToErase != 2) vEdgeVertex[0].push_back( ptTR) ; - if( nVertToErase != 3) + if ( nVertToErase != 3) vEdgeVertex[1].push_back( ptTl) ; - if( nVertToErase != 0) + if ( nVertToErase != 0) vEdgeVertex[2].push_back( ptBL) ; - if( nVertToErase != 1) + if ( nVertToErase != 1) vEdgeVertex[3].push_back( ptBr) ; // capisco se sono in modalità ForTriangulation bool bForTriangulation = plCell3d.GetPointNbr() != 0 ; if ( bForTriangulation) { - if( nVertToErase != 2) { + if ( nVertToErase != 2) { Point3d pt3d ; GetPoint( cCell.GetTopRight().x, cCell.GetTopRight().y, pt3d) ; vEdgeVertex3d[0].push_back( pt3d) ; } - if( nVertToErase != 3){ + if ( nVertToErase != 3) { Point3d pt3d ; GetPoint( cCell.GetBottomLeft().x, cCell.GetTopRight().y, pt3d) ; vEdgeVertex3d[1].push_back( pt3d) ; } - if( nVertToErase != 0) { + if ( nVertToErase != 0) { Point3d pt3d ; GetPoint( cCell.GetBottomLeft().x, cCell.GetBottomLeft().y, pt3d) ; vEdgeVertex3d[2].push_back( pt3d) ; } - if( nVertToErase != 1) { + if ( nVertToErase != 1) { Point3d pt3d ; GetPoint( cCell.GetTopRight().x, cCell.GetBottomLeft().y, pt3d) ; vEdgeVertex3d[3].push_back( pt3d) ; } } - - - // la PolyLine è riempita a partire dal lato bottom + // la PolyLine è riempita a partire dal lato bottom Point3d ptStart, pt3d ; plCell.GetFirstPoint( ptStart) ; if ( bForTriangulation) @@ -3052,7 +3087,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX if ( dArea > 0) { vPolygons.emplace_back() ; vPolygons.back().push_back(std::move(plTrimmedPoly)) ; - if( bForTriangulation) { + if ( bForTriangulation) { vPolygons3d.emplace_back() ; vPolygons3d.back().push_back(std::move(plTrimmedPoly3d)) ; } @@ -3108,7 +3143,7 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR nChunkBiggestCW = inA.nChunk ; bContained = false ; Inters inB = cCell.m_vInters[0] ; - for( int c = 0 ; c < nInters ; ++ c){ + for ( int c = 0 ; c < nInters ; ++ c){ inB = cCell.m_vInters[c] ; if ( inB.nIn == -1) { if ( inB != inA && inB.nChunk == inA.nChunk && inB.bCCW) { @@ -3367,12 +3402,12 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe int nVertToSkip = m_mTree.at(nId).m_nVertToErase ; // se è il primo punto della PolyLine lo aggiungo if ( plTrimmedPoly.GetPointNbr() == 0) { - // se cerco di aggiungere il vertice che devo saltare, non faccio nulla - if( ( nVertToSkip == 0 && AreSamePointXYApprox( ptToAdd, ptBL)) || + // se cerco di aggiungere il vertice che devo saltare, non faccio nulla + if (( nVertToSkip == 0 && AreSamePointXYApprox( ptToAdd, ptBL)) || ( nVertToSkip == 1 && AreSamePointXYApprox( ptToAdd, ptBr)) || ( nVertToSkip == 2 && AreSamePointXYApprox( ptToAdd, ptTR)) || ( nVertToSkip == 3 && AreSamePointXYApprox( ptToAdd, ptTl))) { - // aggiorno l'ultimo punto aggiunto + // aggiorno l'ultimo punto aggiunto ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ; return true ; } @@ -3421,7 +3456,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ptVert = ptToAdd ; if ( nVert != nVertToSkip) { plTrimmedPoly.AddUPoint( c, ptVert) ; - if( bForTriangulation){ + if ( bForTriangulation){ Point3d pt3d ; GetPoint( ptVert.x, ptVert.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -3439,7 +3474,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[0][t] ; if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - if( bForTriangulation) + if ( bForTriangulation) plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[0][t]) ; ++ c ; } @@ -3447,7 +3482,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe bool bVert = AreSamePointXYApprox( ptToAdd, ptTl) ; if ( ! ( nVertToSkip == 3 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation){ + if ( bForTriangulation){ Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -3460,7 +3495,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[1][t] ; if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - if( bForTriangulation) + if ( bForTriangulation) plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[1][t]) ; ++ c ; } @@ -3468,7 +3503,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe bool bVert = AreSamePointXYApprox( ptToAdd, ptBL) ; if ( ! ( nVertToSkip == 0 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation) { + if ( bForTriangulation) { Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -3481,7 +3516,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[2][t] ; if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - if( bForTriangulation) + if ( bForTriangulation) plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[2][t]) ; ++ c ; } @@ -3489,7 +3524,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe bool bVert = AreSamePointXYApprox( ptToAdd, ptBr) ; if ( ! ( nVertToSkip == 1 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation){ + if ( bForTriangulation){ Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -3502,7 +3537,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptIntermed = vEdgeVertex[3][t] ; if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; - if( bForTriangulation) + if ( bForTriangulation) plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[3][t]) ; ++ c ; } @@ -3510,7 +3545,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe bool bVert = AreSamePointXYApprox( ptToAdd, ptTR) ; if ( ! ( nVertToSkip == 2 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation) { + if ( bForTriangulation) { Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -3521,7 +3556,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe // aggiungo e basta else { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation) { + if ( bForTriangulation) { Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -3531,7 +3566,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe // non su un edge, quindi aggiungo e basta else { plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation) { + if ( bForTriangulation) { Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ; plTrimmedPoly3d.AddUPoint( c, pt3d) ; } @@ -4010,14 +4045,14 @@ Tree::GetEdges3D( vector& mCCEdges, POLYLINEVECTOR& vPolygons // scorro sui poligoni delle celle di un lato for ( int c = 0 ; c < int( vEdges[i].size()) ; ++c) { Cell& cNeigh = m_mTree.at(vEdges[i][c]) ; - if( cNeigh.m_vnPolyId.empty()) + if ( cNeigh.m_vnPolyId.empty()) continue ; PolyLine& plCell = vPolygons[cNeigh.m_vnPolyId[0]] ; Point3d pt ; plCell.GetFirstPoint( pt) ; Point3d pt3d ; // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato if ( i == 0) { - while ( ! AreSamePointXYApprox(pt, cNeigh.GetTopRight()) && plCell.GetNextPoint(pt) ) { + while ( ! AreSamePointXYApprox(pt, cNeigh.GetTopRight()) && plCell.GetNextPoint(pt)) { continue ; } Point3d pt3d ; GetPoint( cNeigh.GetTopRight().x, cNeigh.GetTopRight().y, pt3d) ; @@ -4090,13 +4125,13 @@ Tree::GetEdges3D( vector& mCCEdges, POLYLINEVECTOR& vPolygons mCCEdges.emplace_back() ; INTVECTOR vId ; Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ; - while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) { + while ( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId)) { PtrOwner pCC3D( CreateCurveComposite()) ; int nInd = abs( vId[0]) - 1 ; Point3d pt2D = m_vCEdge2D[i].first[nInd].first ; Point3d pt3D ; GetPoint( pt2D.x, pt2D.y, pt3D) ; pCC3D->AddPoint( pt3D) ; - for ( int j = 1 ; j < int( vId.size()) ; ++j) { + for ( int j = 1 ; j < ssize( vId) ; ++j) { nInd = abs( vId[j]) - 1 ; pt2D = m_vCEdge2D[i].first[nInd].second ; GetPoint( pt2D.x, pt2D.y, pt3D) ; @@ -4105,7 +4140,7 @@ Tree::GetEdges3D( vector& mCCEdges, POLYLINEVECTOR& vPolygons if ( ! pCC3D->IsValid()) pCC3D->AddPoint( pt3D) ; // qui devo fare dei controlli prima di aggiungere questa polyline? - mCCEdges[i].emplace_back( Release(pCC3D)) ; + mCCEdges[i].emplace_back( Release( pCC3D)) ; } } } @@ -4225,11 +4260,11 @@ Tree::AdjustCuts( void) bool Tree::CreateCellContour( POLYLINEMATRIX& vPolygons) { - // questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli + // questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli if ( m_mTree.size() > 1) return false ; int nRoot = -1 ; - // preparo tutto per poter chiamare la createCellPolygon + // preparo tutto per poter chiamare la createCellPolygon m_vnLeaves.push_back( nRoot) ; INTVECTOR vToCheck( m_mTree.at(nRoot).m_vInters.size()) ; iota( vToCheck.begin(), vToCheck.end(), 0) ; @@ -4254,7 +4289,7 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons) pl3d.Close() ; // ora posso creare il poligono della cella con i tagli POLYLINEMATRIX vPolygons3d ; - while( ! vToCheck.empty()) { + while ( ! vToCheck.empty()) { int nPolyBefore = nPoly ; CreateCellPolygons( 0, vPolygons, vPolygons3d, vToCheck, nPoly, vnParentChunk, pl, pl3d) ; // l'aggiunta di vPolygons3d forse è un problema in questo punto. @@ -4264,4 +4299,4 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons) break ; } return true ; -} \ No newline at end of file +} diff --git a/VolZmap.cpp b/VolZmap.cpp index fdc44d8..c435347 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -507,11 +507,15 @@ VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const } // passo al punto successivo dX += m_dStep ; + if ( m_nMapNum == N_MAPS) + dX = min( dX, m_dMaxZ[1]) ; } // passo alla riga successiva dY += m_dStep ; + if ( m_nMapNum == N_MAPS) + dY = min( dY, m_dMaxZ[2]) ; } -// + return true ; } @@ -551,9 +555,13 @@ VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const } // passo al punto successivo dX += m_dStep ; + if ( m_nMapNum == N_MAPS) + dX = min( dX, m_dMaxZ[1]) ; } // passo alla riga successiva dY += m_dStep ; + if ( m_nMapNum == N_MAPS) + dY = min( dY, m_dMaxZ[2]) ; } return true ; diff --git a/VolZmap.h b/VolZmap.h index ee53485..c8d6f76 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -472,15 +472,18 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool UpdateVolZMapBySurfThickeningSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ; bool CreateOffsetSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ; bool CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ; - bool CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle) ; + bool CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle, int nTool = 0) ; bool CreateOrientedOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs) ; bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum, bool bSkipSwap = false) ; bool AddIntervalsForOffset( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, - int nToolNum, bool bSkipSwap = false) ; + int nToolMin, int nToolMax, bool bSkipSwap = false) ; bool CutByPlaneForOffset( const Plane3d& plCut) ; + bool AddSurfTmForOffset( const ISurfTriMesh* pStm, int nTool) ; + bool AddMapPartForOffset( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, int nTool, IntersParLinesSurfTm& intPLSTM) ; // Funzioni per Offset di Zmap bool OffsetFillet( double dOffs) ; bool OffsetSharped( double dOffs, int nType) ; diff --git a/VolZmapCalculus.cpp b/VolZmapCalculus.cpp index 4786ba9..178f2ae 100644 --- a/VolZmapCalculus.cpp +++ b/VolZmapCalculus.cpp @@ -2294,7 +2294,7 @@ VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir, vtN1.Normalize() ; } // altrimenti piano inferiore - else if( nBasInt == 1) { + else if ( nBasInt == 1) { // Punto di intersezione ptInt2 = ptP + vdRoots[0] * vtV ; // Normale alla superficie del cono verso l'interno @@ -3080,17 +3080,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c return false ; // Se c'è intersezione valuto tutti i voxel interni if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) { - // Ciclo sui voxel del blocco. // Triangoli smooth - for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) { + // ciclo sui voxel del blocco. + for ( int nV = 0 ; nV < ssize( m_BlockSmoothTria[nB]) ; ++ nV) { // Box del voxel BBox3d b3Vox ; GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ; - // Se non c'è intersezione col voxel, passo al successivo. + // Se non c'è intersezione col voxel, passo al successivo. if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox)) continue ; - for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) { - Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ; + // ciclo sui triangoli del voxel + for ( int nT = 0 ; nT < ssize( m_BlockSmoothTria[nB][nV].vTria) ; ++ nT) { + const Triangle3d& trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ; Point3d ptSt, ptEn ; int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ; if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) { @@ -3102,18 +3103,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c } } // Triangoli sharp interni al blocco - for ( int nV = 0 ; nV < int( m_BlockSharpTria[nB].size()) ; ++ nV) { + // ciclo sui voxel del blocco. + for ( int nV = 0 ; nV < ssize( m_BlockSharpTria[nB]) ; ++ nV) { // Box del voxel BBox3d b3Vox ; GetVoxelBox( m_BlockSharpTria[nB][nV].i, m_BlockSharpTria[nB][nV].j, m_BlockSharpTria[nB][nV].k, b3Vox) ; - // Se non c'è intersezione col voxel, passo al successivo. // Ciclo sulle componenti connesse - for ( int nC = 0 ; nC < int( m_BlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) { - for ( int nT = 0 ; nT < int( m_BlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) { - Triangle3d trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ; + for ( int nC = 0 ; nC < ssize( m_BlockSharpTria[nB][nV].vCompoTria) ; ++ nC) { + for ( int nT = 0 ; nT < ssize( m_BlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) { + const Triangle3d& trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ; Point3d ptSt, ptEn ; - int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ; - if (nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) { + int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ; + if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) { // Costruisco il tratto di curva CurveLine cvLine ; if ( cvLine.Set(ptSt, ptEn)) @@ -3123,10 +3124,10 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c } } // Triangoli grandi del blocco - for ( int nT = 0 ; nT < int( m_BlockBigTria[nB].size()) ; ++ nT) { - Triangle3d trTria = m_BlockBigTria[nB][nT] ; + for ( int nT = 0 ; nT < ssize( m_BlockBigTria[nB]) ; ++ nT) { + const Triangle3d& trTria = m_BlockBigTria[nB][nT] ; Point3d ptSt, ptEn ; - int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ; + int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ; if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) { // Costruisco il tratto di curva CurveLine cvLine ; @@ -3136,11 +3137,11 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c } } // In ogni caso valuto i triangoli sharp fra blocchi - for ( int nV = 0 ; nV < int( m_InterBlockSharpTria[nB].size()) ; ++ nV) { + for ( int nV = 0 ; nV < ssize( m_InterBlockSharpTria[nB]) ; ++ nV) { // Ciclo sulle componenti connesse - for ( int nC = 0 ; nC < int( m_InterBlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) { - for ( int nT = 0 ; nT < int( m_InterBlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) { - Triangle3d trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ; + for ( int nC = 0 ; nC < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria) ; ++ nC) { + for ( int nT = 0 ; nT < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) { + const Triangle3d& trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ; Point3d ptSt, ptEn ; int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ; if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) { @@ -3156,9 +3157,9 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c // Creo i loop ChainCurves LoopCreator ; - LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ; + LoopCreator.Init( false, EPS_SMALL, ssize( vLine)) ; // Carico le curve per concatenarle - for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) { + for ( int nCv = 0 ; nCv < ssize( vLine) ; ++ nCv) { Point3d ptSt = vLine[nCv].GetStart() ; Point3d ptEn = vLine[nCv].GetEnd() ; Vector3d vtDir; vLine[nCv].GetStartDir(vtDir) ; diff --git a/VolZmapOffset.cpp b/VolZmapOffset.cpp index 6331891..a4e62d8 100644 --- a/VolZmapOffset.cpp +++ b/VolZmapOffset.cpp @@ -275,10 +275,357 @@ VolZmap::SubtractIntervalsForOffset( int nGrid, int nI, int nJ, bool VolZmap::AddIntervalsForOffset( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, - int nToolNum, bool bSkipSwap) + int nToolMin, int nToolMax, bool bSkipSwap) { - // TODO -- Aggiustare eventuali tolleranze - return AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ; + // Controllo che il numero di griglia sia entro i limiti + if ( nGrid < 0 || nGrid > 2) + return false ; + + // Controllo che indici nI, nJ siano entro i limiti + if ( nI < 0 || nI >= m_nNx[nGrid] || + nJ < 0 || nJ >= m_nNy[nGrid]) + return false ; + + // Controllo che dMin < dMax + Vector3d vtNmi = vtNMin ; + Vector3d vtNma = vtNMax ; + if ( dMin > dMax) { + swap( dMin, dMax) ; + swap( vtNmi, vtNma) ; + } + + // Restringo minimo e massimo entro i limiti della mappa + if ( dMin < m_dMinZ[nGrid]) { + dMin = m_dMinZ[nGrid] ; + if ( ! bSkipSwap) + vtNmi = - Z_AX ; + } + else if ( dMin > m_dMaxZ[nGrid]) { + dMin = m_dMaxZ[nGrid] ; + if ( ! bSkipSwap) + vtNmi = - Z_AX ; + } + if ( dMax < m_dMinZ[nGrid]) { + dMax = m_dMinZ[nGrid] ; + if ( ! bSkipSwap) + vtNma = Z_AX ; + } + else if ( dMax > m_dMaxZ[nGrid]) { + dMax = m_dMaxZ[nGrid] ; + if ( ! bSkipSwap) + vtNma = Z_AX ; + } + + // Controllo che dMin e dMax non siano quasi coincidenti + if ( abs( dMax - dMin) < EPS_SMALL) + return true ; + + // Riporto le coordinate cicliche nell'ordine di partenza + if ( !bSkipSwap && nGrid == 1) { + swap( vtNmi.x, vtNmi.z) ; + swap( vtNmi.y, vtNmi.z) ; + swap( vtNma.x, vtNma.z) ; + swap( vtNma.y, vtNma.z) ; + } + else if ( !bSkipSwap && nGrid == 2) { + swap( vtNmi.y, vtNmi.z) ; + swap( vtNmi.x, vtNmi.z) ; + swap( vtNma.y, vtNma.z) ; + swap( vtNma.x, vtNma.z) ; + } + + // Calcolo nPos + int nPos = nJ * m_nNx[nGrid] + nI ; + vector& vDexel = m_Values[nGrid][nPos] ; + + bool bModified = false ; + + // Non esistono segmenti + if ( vDexel.empty()) { + + vDexel.emplace_back() ; + vDexel.back().dMin = dMin ; + vDexel.back().vtMinN = vtNmi ; + vDexel.back().nToolMin = nToolMin ; + vDexel.back().dMax = dMax ; + vDexel.back().vtMaxN = vtNma ; + vDexel.back().nToolMax = nToolMax ; + + m_OGrMgr.Reset() ; + + bModified = true ; + } + // Esiste almeno un segmento + else { + // Cerco l'ultimo intervallo a sinistra e l'ultimo intervallo a destra + // di quello da aggiungere, che non interferiscono con quest'ultimo. + auto itLastLeft = vDexel.end() ; + auto itFirstRight = vDexel.end() ; + for ( auto it = vDexel.begin() ; it != vDexel.end() ; ++ it) { + if ( dMin > it->dMax + EPS_SMALL) + itLastLeft = it ; + if ( dMax < it->dMin - EPS_SMALL && itFirstRight == vDexel.end()) + itFirstRight = it ; + } + // Esistono intervalli a sinistra. + if ( itLastLeft != vDexel.end()) { + // Intervallo successivo all'ultimo a sinistra + auto itNextToLastLeft = itLastLeft ; + ++ itNextToLastLeft ; + // Il successivo non esiste. + if ( itNextToLastLeft == vDexel.end()) { + // Aggiungo il nuovo segmento + vDexel.emplace_back() ; + vDexel.back().dMin = dMin ; + vDexel.back().dMax = dMax ; + vDexel.back().vtMinN = vtNmi ; + vDexel.back().vtMaxN = vtNma; + vDexel.back().nToolMin = nToolMin ; + vDexel.back().nToolMax = nToolMax ; + bModified = true ; + } + // Il successivo esiste. + else { + // Il successivo è il primo a destra. + if ( itNextToLastLeft == itFirstRight) { + // Inserisco nuovo segmento + Data NewSegment ; + NewSegment.dMin = dMin ; + NewSegment.dMax = dMax ; + NewSegment.vtMinN = vtNmi ; + NewSegment.vtMaxN = vtNma ; + NewSegment.nToolMin = nToolMin ; + NewSegment.nToolMax = nToolMax ; + //NewSegment.nCompo = ; + vDexel.insert( itFirstRight, NewSegment) ; + bModified = true ; + } + else { + // Il successivo non esce a sinistra da quello da aggiungere. + if ( itNextToLastLeft->dMin > dMin + EPS_SMALL) { + itNextToLastLeft->dMin = dMin ; + itNextToLastLeft->vtMinN = vtNmi ; + itNextToLastLeft->nToolMin = nToolMin ; + } + // Cerco l'ultimo segmento che interferisce con quello da aggiungere. + auto itPrevToFirstRight = vDexel.end() ; + for ( auto it = itNextToLastLeft ; it != itFirstRight ; ++ it) { + itPrevToFirstRight = it ; + } + // L'ultimo che interferisce non esce a destra da quello da aggiungere. + if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) { + itNextToLastLeft->dMax = dMax ; + itNextToLastLeft->vtMaxN = vtNma ; + itNextToLastLeft->nToolMax = nToolMax ; + bModified = true ; + } + else { + itNextToLastLeft->dMax = itPrevToFirstRight->dMax ; + itNextToLastLeft->vtMaxN = itPrevToFirstRight->vtMaxN ; + itNextToLastLeft->nToolMax = nToolMax ; + bModified = true ; + } + auto itFirstToCancel = itNextToLastLeft ; + ++ itFirstToCancel ; + vDexel.erase( itFirstToCancel, itFirstRight) ; + } + } + } + // Non esistono neanche a destra. + else if ( itFirstRight == m_Values[nGrid][nPos].end()) { + // Il primo intervallo non sporge a sinistra + if ( vDexel.begin()->dMin > dMin + EPS_SMALL) { + vDexel.begin()->dMin = dMin ; + vDexel.begin()->vtMinN = vtNmi ; + vDexel.begin()->nToolMin = nToolMin ; + bModified = true ; + } + // L'ultimo intervallo sporge a destra. + if ( m_Values[nGrid][nPos].back().dMax > dMax + EPS_SMALL) { + // Ci sono più segmenti, inglobo tutti nel primo. + if ( vDexel.back().dMax > vDexel.begin()->dMax + EPS_SMALL) { + vDexel.begin()->dMax = vDexel.back().dMax ; + vDexel.begin()->vtMaxN = vDexel.back().vtMaxN ; + vDexel.begin()->nToolMax = nToolMax ; + bModified = true ; + } + } + // L'ultimo intervallo non sporge a destra. + else { + vDexel.begin()->dMax = dMax ; + vDexel.begin()->vtMaxN = vtNma ; + vDexel.begin()->nToolMax = nToolMax ; + bModified = true ; + } + vDexel.erase( vDexel.begin() + 1, vDexel.end()) ; + } + // A destra esistono. + else { + // Tutti i segmenti sono a destra di qullo da aggiungere. + if ( itFirstRight == vDexel.begin()) { + // Inserisco nuovo segmento- + Data NewSegment ; + NewSegment.dMin = dMin ; + NewSegment.dMax = dMax ; + NewSegment.vtMinN = vtNmi ; + NewSegment.vtMaxN = vtNma ; + NewSegment.nToolMin = nToolMin ; + NewSegment.nToolMax = nToolMax ; + vDexel.insert( vDexel.begin(), NewSegment) ; + bModified = true ; + } + else { + // Se il primo segmento non esce a sinistra da quello da aggiungere, cambio l'inizio. + if ( vDexel.begin()->dMin > dMin + EPS_SMALL) { + vDexel.begin()->dMin = dMin ; + vDexel.begin()->vtMinN = vtNmi ; + vDexel.begin()->nToolMin = nToolMin ; + bModified = true ; + } + // Cerco l'ultimo segmento che interferisce con quello da aggiungere. + auto itPrevToFirstRight = vDexel.begin() ; + for ( auto it = m_Values[nGrid][nPos].begin() ; it != itFirstRight ; ++ it) { + itPrevToFirstRight = it ; + } + // L'ultimo che interferisce non esce a destra da quello da aggiungere. + if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) { + vDexel.begin()->dMax = dMax ; + vDexel.begin()->vtMaxN = vtNma ; + vDexel.begin()->nToolMax = nToolMax ; + bModified = true ; + } + else { + vDexel.begin()->dMax = itPrevToFirstRight->dMax ; + vDexel.begin()->vtMaxN = itPrevToFirstRight->vtMaxN ; + vDexel.begin()->nToolMax = nToolMax ; + bModified = true ; + } + auto itFirstToCancel = vDexel.begin() ; + ++ itFirstToCancel ; + vDexel.erase( itFirstToCancel, itFirstRight) ; + } + } + } + + // Se nessuna modifica, esco + if ( ! bModified) + return true ; + + // Imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + // Imposto forma generica + m_nShape = GENERIC ; + // Imposto ricalcolo numero di componenti connesse + m_nConnectedCompoCount = - 1 ; + + // Passo da indici di dexel a indici di voxel + nI /= m_nDexVoxRatio ; + nJ /= m_nDexVoxRatio ; + + // Determino quali blocchi sono stati modificati + if ( nGrid == 0) { + // Voxel lungo X + int nXStop = 1 ; + int nXBlock[2] ; + nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; + if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) { + nXBlock[1] = nXBlock[0] - 1 ; + ++ nXStop ; + } + // Voxel lungo Y + int nYStop = 1 ; + int nYBlock[2] ; + nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; + if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) { + nYBlock[1] = nYBlock[0] - 1 ; + ++ nYStop ; + } + // Voxel lungo Z + int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; + int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ; + int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ; + int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ; + // Assegno flag ai voxel + for ( int tI = 0 ; tI < nXStop ; ++ tI) { + for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) { + for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) { + int nBlockNum = k * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ; + m_BlockToUpdate[nBlockNum] = true ; + } + } + } + } + + else if ( nGrid == 1) { + // Voxel lungo Y + int nYStop = 1 ; + int nYBlock[2] ; + nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; + if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) { + nYBlock[1] = nYBlock[0] - 1 ; + ++ nYStop ; + } + // Voxel lungo Z + int nZStop = 1 ; + int nZBlock[2] ; + nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; + if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) { + nZBlock[1] = nZBlock[0] - 1 ; + ++ nZStop ; + } + // Voxel lungo X + int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ; + int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ; + int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ; + int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ; + // Assegno flag ai voxel + for ( int tI = 0 ; tI < nYStop ; ++ tI) { + for ( int tJ = 0 ; tJ < nZStop ; ++ tJ) { + for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) { + int nBlockNum = nZBlock[tJ] * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tI] * m_nFracLin[0] + k ; + m_BlockToUpdate[nBlockNum] = true ; + } + } + } + } + + else if ( nGrid == 2) { + // Voxel lungo X + int nXStop = 1 ; + int nXBlock[2] ; + nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; + if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) { + nXBlock[1] = nXBlock[0] - 1 ; + ++ nXStop ; + } + // Voxel lungo Z + int nZStop = 1 ; + int nZBlock[2] ; + nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; + if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) { + nZBlock[1] = nZBlock[0] - 1 ; + ++ nZStop ; + } + // Voxel lungo Y + int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; + int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ; + int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ; + int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ; + // Assegno flag ai voxel + for ( int tI = 0 ; tI < nZStop ; ++ tI) { + for ( int tJ = 0 ; tJ < nXStop ; ++ tJ) { + for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) { + int nBlockNum = nZBlock[tI] * m_nFracLin[0] * m_nFracLin[1] + k * m_nFracLin[0] + nXBlock[tJ] ; + m_BlockToUpdate[nBlockNum] = true ; + } + } + } + } + + return true ; } //---------------------------------------------------------------------------- @@ -349,6 +696,194 @@ VolZmap::CutByPlaneForOffset( const Plane3d& plCut) return true ; } +//---------------------------------------------------------------------------- +// Funzione per aggiungere allo ZMap quello di una TriMesh chiusa +// --------------------------------------------------------------------------- +bool +VolZmap::AddSurfTmForOffset( const ISurfTriMesh* pStm, int nTool) +{ + // controllo sulla superficie + double dVol ; + if ( pStm == nullptr || ! pStm->IsValid() || ! pStm->IsClosed() || + ! pStm->GetVolume( dVol) || dVol < 0) + return false ; + + // controllo se il Box3d della superficie si interseca con il Box3d dello Zmap corrente + BBox3d BBox_stm, BBox_curr ; + if ( ! pStm->GetLocalBBox( BBox_stm) || ! GetLocalBBox( BBox_curr)) + return false ; + BBox3d BBox_inters ; + if ( BBox_stm.FindIntersection( BBox_curr, BBox_inters) && BBox_inters.IsEmpty()) + return true ; // se non ci sono intersezioni, la superficie non influenza lo Zmap + Vector3d vtLen = BBox_curr.GetMax() - BBox_curr.GetMin() ; // dimensione massima dello spillone + + // ciclo sulle griglie + bool bCompleted = true ; + for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) { + // definisco dei sistemi di riferimento ausiliari + Frame3d frMapFrame ; + if ( nG == 0) + frMapFrame = m_MapFrame ; + else if ( nG == 1) + frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ; + else if ( nG == 2) + frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ; + + // oggetto per calcolo massivo intersezioni + IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ; + + // numero massimo di thread + int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ; + vector> vRes ; + vRes.resize( nThreadMax) ; + // se dimensione griglia in X maggiore di dimensione Y + if ( m_nNx[nG] > m_nNy[nG]) { + int nDexNum = m_nNx[nG] / nThreadMax ; + int nRemainder = m_nNx[nG] % nThreadMax ; + int nInfI = 0 ; + int nSupI = 0 ; + // aggiungo le parti interessate alla mappa + for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { + nInfI = nSupI ; + nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; + vRes[nThread] = async( launch::async, &VolZmap::AddMapPartForOffset, this, nG, + nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( m_MapFrame.Orig()), + ref( *pStm), nTool, ref( intPLSTM)) ; + } + } + // se dimensione griglia in Y maggiore di dimensione X + else { + int nDexNum = m_nNy[nG] / nThreadMax ; + int nRemainder = m_nNy[nG] % nThreadMax ; + int nInfJ = 0 ; + int nSupJ = 0 ; + // aggiungo le parti interessate alla mappa + for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { + nInfJ = nSupJ ; + nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; + vRes[nThread] = async( launch::async, &VolZmap::AddMapPartForOffset, this, nG, + 0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()), + ref( *pStm), nTool, ref( intPLSTM)) ; + } + } + + // ciclo per attendere che tutti gli async abbiano terminato. + int nTerminated = 0 ; + while ( nTerminated < nThreadMax) { + for ( int nL = 0 ; nL < nThreadMax ; ++ nL) { + // async terminato + if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) { + ++ nTerminated ; + bCompleted = bCompleted && vRes[nL].get() ; + } + } + } + + if ( ! bCompleted) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +// Funzione per aggiungere gli Spilloni di una TriMesh chiusa allo ZMap corrente +//---------------------------------------------------------------------------- +bool +VolZmap::AddMapPartForOffset( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, + const Vector3d& vtLen, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, int nTool, IntersParLinesSurfTm& intPLSTM) +{ + // controllo sui parametri + if ( nMap < 0 || nMap > 2 || + nInfI < 0 || nInfI > m_nNx[nMap] || + nSupI < 0 || nSupI > m_nNx[nMap] || + nInfJ < 0 || nInfJ > m_nNy[nMap] || + nSupJ < 0 || nSupJ > m_nNy[nMap]) + return false ; + + // determinazione e ridimensionamento dei dexel interni alla trimesh + for ( int i = nInfI ; i < nSupI ; ++ i) { + for ( int j = nInfJ ; j < nSupJ ; ++ j) { + + // definisco la retta da intersecare con la trimesh + double dX = ( i + 0.5) * m_dStep ; + double dY = ( j + 0.5) * m_dStep ; + Point3d ptP0( dX, dY, 0) ; + + // intersezioni della retta con la TriMesh + ILSIVECTOR IntersectionResults ; + intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ; + + // rimuovo le intersezioni in eccesso + for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) { + int nJ = nI + 1 ; // prima successiva + int nK = nJ + 1 ; // seconda successiva + int nT = nK + 1 ; // terza successiva + // determino i segni delle 4 intersezioni tra la linea e il trangolo della TriMesh + int nSgnI = IntersectionResults[nI].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nI].dCosDN > -EPS_SMALL ? 0 : - 1 ; + int nSgnJ = IntersectionResults[nJ].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nJ].dCosDN > -EPS_SMALL ? 0 : - 1 ; + int nSgnK = IntersectionResults[nK].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nK].dCosDN > -EPS_SMALL ? 0 : - 1 ; + int nSgnT = IntersectionResults[nT].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nT].dCosDN > -EPS_SMALL ? 0 : - 1 ; + // parametri dell'intersezione sulla linea + double dUJ = IntersectionResults[nJ].dU ; + double dUK = IntersectionResults[nK].dU ; + // controllo coerenza con segni... + if ( nSgnI != 0 && nSgnI == nSgnJ && + nSgnK != 0 && nSgnK == nSgnT && + nSgnI == - nSgnT && + abs( dUJ - dUK) < EPS_SMALL) { + // ... ed elimino le intersezioni in eccesso... + IntersectionResults.erase( IntersectionResults.begin() + nK) ; + IntersectionResults.erase( IntersectionResults.begin() + nJ) ; + } + } + + int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide + bool bInside = false ; // Flag entrata/uscita per tratto di retta + Point3d ptIn ; Vector3d vtInN ; + + // per ogni intersezione valida trovata... + int nFlagIn = 0 ; + for ( int k = 0 ; k < nInt ; ++ k) { + // ricavo il tipo di intersezione + int nIntType = IntersectionResults[k].nILTT ; + // se c'è intersezione + if ( nIntType != ILTT_NO) { + // ricavo il cos tra i vettori ( normale del triangolo e tangente alla retta) + double dCos = IntersectionResults[k].dCosDN ; + + // se entro nella superficie trimesh... + if ( dCos < - EPS_SMALL) { + ptIn = IntersectionResults[k].ptI ; // punto di intersezione + int nT = IntersectionResults[k].nT ; // triangolo di interesse + int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse + Surf.GetFacetNormal( nF, vtInN) ; // normale della faccia + Surf.GetTFlag( nT, nFlagIn) ; // nFlag entrata dalla faccia + bInside = true ; // entrata + } + // ...se esco dalla superficie trimesh ( prima sono per forza entrato) + else if ( dCos > EPS_SMALL && bInside) { + Point3d ptOut = IntersectionResults[k].ptI ; // punto di intersezione + int nT = IntersectionResults[k].nT ; // triangolo di interesse + int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse + Vector3d vtOutN ; Surf.GetFacetNormal( nF, vtOutN) ; // vettore d'uscita + int nFlagOut = 0 ; Surf.GetTFlag( nT, nFlagOut) ; // nFlag uscita dalla faccia + + // Aggiungo un tratto al dexel + AddIntervalsForOffset( nMap, i, j, + ptIn.v[( nMap + 2) % 3] - ptMapOrig.v[( nMap + 2) % 3], + ptOut.v[( nMap + 2) % 3] - ptMapOrig.v[( nMap + 2) % 3], + vtInN, vtOutN, nTool, nTool, true) ; + bInside = false ; // uscita + } + } + } + } + } + + return true ; +} //---------------------------------------------------------------------------- // Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui @@ -381,7 +916,7 @@ VolZmap::CreateOffsetSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid Vector3d vtNmax = Point3d( dX, dY, dMax) - ptV ; vtNmax.Normalize() ; if ( dOffs > 0.) - AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool) ; + AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool, nTool) ; else SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, nTool) ; } @@ -396,7 +931,8 @@ VolZmap::CreateOffsetSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid // aggiungere o sottrarre intervalli lungo i Dexel coinvolti. //---------------------------------------------------------------------------- bool -VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nTool) +VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, + int nGrid, int nTool) { // determino la lunghezza dello spigolo corrente double dH = Dist( ptP1, ptP2) ; @@ -435,7 +971,7 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true, ptInt1, vtN1, ptInt2, vtN2)) { if ( dOffs > 0.) - AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ; + AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ; else SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ; } @@ -450,7 +986,8 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d // aggiungere o sottrarre intervalli lungo i Dexel coinvolti //---------------------------------------------------------------------------- bool -VolZmap::CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle) +VolZmap::CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle, + int nTool) { // verifico la validità della superficie if ( Surf == nullptr) @@ -489,10 +1026,11 @@ VolZmap::CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, b } return false ; } + // aggiorno gli spilloni // se Offset Thickle allora sommo tutti i contributi senza tener conto del segno dell'Offset if ( bThickle) { - AddSurfTm( pStmExtr) ; + AddSurfTmForOffset( pStmExtr, nTool) ; } // se Offset orientato, allora aggiungo o sottraggo gli intervalli a seconda del segno di Offset else { @@ -1024,7 +1562,6 @@ VolZmap::UpdateVolZMapByClosedSurfSharpedOffset( const ISurfTriMesh* Surf, int n return true ; } - //---------------------------------------------------------------------------- // [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente // mediante una superficie aperta @@ -1039,25 +1576,75 @@ VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double d if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) return true ; - // Assunzioni : - // - Idea Generale di Offset - // - Su ogni faccia viene definita una superficie di estrusione ( dove le basi sono - // definite dalla traslazione o in positivo o in negativo della faccia lungo la sua normale - // orientata coerentemente in base al segno dell'offset) - // - Su ogni lato viene definita una porzione di cilindro orientata ( estrusione di uno spicchio) - // - Su ogni vertice viene definita una sfera che viene tagliata con i piani definiti - // dalle facce delle porzioni di cilindro + // definisco vettore di frame Locali alle 3 griglie + FRAME3DVECTOR vFrGrid( 4) ; + vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ; + vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ; + vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ; + vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ; - // ----------------------- Facce ----------------------- - if ( ! CreateOrientedOffsetExtrusionFace( Surf, dOffs)) - return true ; + // creo lo Zmap di Thickening : + // l'Offset di thickening può essere scomposto in 3 parti : + // - Offset positivo + // - Offset negativo + // - Raccordi + // l'idea è proprio quella di rimuovere i raccordi dall'Offset thickening mediante + // sottrazione di ZMap ( e successivamente classificare il Side dei triangoli) - // definisco una mappa tra vertici e contorni orientati degli ZMap derivanti dagli Edges adiacenti - // }, { vector }> - unordered_map, vector>> vMapVertBorders( Surf->GetVertexCount()) ; - - // ----------------------- spicchi ----------------------- + // creazione dello ZMap di Thicking della superficie + // [NB. potrebbero esserci modifiche ed ottimizzazioni, quindi non richiamo la funzione di + // Offset thicking direttamente ma ne copio le varie parti] [TODO] + INTVECTOR vOpenEdges ; vOpenEdges.reserve( Surf->GetEdgeCount()) ; + INTVECTOR vOpenVertex ; vOpenVertex.reserve( Surf->GetVertexCount()) ; + BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ; for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) { + int nV1, nV2, nF1, nF2 ; double dAng ; + Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ; + // se non è un Edge libero, passo al successivo + if ( nF1 == SVT_NULL || nF2 == SVT_NULL) { + vOpenEdges.push_back( nE) ; + vOpenVertex.push_back( nV1) ; + vOpenVertex.push_back( nV2) ; + continue ; + } + Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ; + Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ; + for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { + ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + if ( ! CreateOffsetCylinderOnEdge( ptP1, ptP2, abs( dOffs), nGrid, 0)) + return false ; + if ( ! vbVert[nV1]) { + if ( ! CreateOffsetSphereOnVertex( ptP1, abs( dOffs), nGrid, 0)) + return false ; + } + if ( ! vbVert[nV2]) { + if ( ! CreateOffsetSphereOnVertex( ptP2, abs( dOffs), nGrid, 0)) + return false ; + } + } + vbVert[nV1] = true ; + vbVert[nV2] = true ; + } + if ( ! CreateFatOffsetExtrusionFace( Surf, abs( dOffs), true, 0)) + return false ; + + #if DEBUG + VT.emplace_back( this->Clone()) ; + VC.emplace_back( FUCHSIA) ; + #endif + + // creo lo Zmap derivante dai semi cilindri orientati + VolZmap VolZMapHalfBorder ; + VolZMapHalfBorder.CreateEmpty( m_MapFrame.Orig(), + m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0], + m_dStep, true) ; + // salvo i piani di taglio per le sfere durante la creazione dei cilindri + unordered_map> vMapVertBorders ; vMapVertBorders.reserve( Surf->GetVertexCount()) ; + + // ----------------------- semicilindri ----------------------- + const double dNewOffs = abs( dOffs) + 3. * m_dStep + 10. * EPS_SMALL ; + for ( const int& nE : vOpenEdges) { // recupero lo spigolo int nV1, nV2, nF1, nF2 ; double dAng ; Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ; @@ -1066,161 +1653,110 @@ VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double d Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ; // definisco il vettore estrusione uscente da ptP1 ed entrante in ptP2 Vector3d vtEdge = ( ptP2 - ptP1) ; + vtEdge.Normalize() ; + + #if DEBUG + CurveLine line ; line.Set( ptP1, ptP2) ; + VT.emplace_back( line.Clone()) ; + Color cCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; + VC.emplace_back( cCol) ; + #endif + // recupero le normali delle facce - Vector3d vtN1, vtN2 ; - Surf->GetFacetNormal( nF1, vtN1) ; - Surf->GetFacetNormal( nF2, vtN2) ; - // --- se lato libero - if ( nF1 == SVT_NULL || nF2 == SVT_NULL) { - // --- non definisco lo spicchio ma aggiungo i piani di taglio - Vector3d vtFaceN = ( nF1 != SVT_NULL ? vtN1 : vtN2) ; - Vector3d vtEdgeN = vtEdge ; - vtEdgeN.Normalize() ; - Vector3d vtPlaneN = vtEdgeN ^ vtFaceN ; - Point3d ptCheck = ptP1 + ( 0.5 * vtEdge) + 5. * EPS_SMALL * vtPlaneN ; - INTVECTOR vnTria ; - Surf->GetAllTriaInFacet( nF1 != SVT_NULL ? nF1 : nF2, vnTria) ; - bool bMirror = false ; - for ( int& nInd : vnTria) { - Triangle3dEx Tria ; - if ( Surf->GetTriangle( nInd, Tria) && IsPointInsideTriangle( ptCheck, Tria, TriangleType::EXACT)) { - bMirror = true ; - break ; + Vector3d vtFaceN ; + if ( nF1 == SVT_NULL) + Surf->GetFacetNormal( nF2, vtFaceN) ; + else + Surf->GetFacetNormal( nF1, vtFaceN) ; + + #if DEBUG + CurveArc myArc ; myArc.SetCPAN( ptP1, ptP1 + dNewOffs * vtFaceN, 360., 0, vtEdge) ; + myArc.SetExtrusion( vtEdge) ; + //myArc.SetThickness( ( ptP2 - ptP1).Len()) ; + CICURVEPVECTOR _vCurve ; + _vCurve.emplace_back( myArc.Clone()) ; + ISurfTriMesh* A = GetSurfTriMeshByRegionExtrusion( _vCurve, ( ptP2 - ptP1).Len() * vtEdge, EPS_SMALL) ; + VT.emplace_back( A) ; + VC.emplace_back( cCol) ; + #endif + + Vector3d vtPlaneN = vtEdge ^ vtFaceN ; + Plane3d plCut ; + plCut.Set( ptP1, - vtPlaneN) ; + // creazione del cilindro + VolZmap VolZMapHalfCyl ; + VolZMapHalfCyl.CreateEmpty( m_MapFrame.Orig(), + m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0], + m_dStep, true) ; + for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { + // esprimo gli estremi nel riferimento della griglia + ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + VolZMapHalfCyl.CreateOffsetCylinderOnEdge( ptP1, ptP2, dNewOffs, nGrid, 0) ; + } + // taglio del cilindro con il piano + VolZMapHalfCyl.CutByPlaneForOffset( plCut) ; + Surf->GetVertex( nV1, ptP1) ; + Surf->GetVertex( nV2, ptP2) ; + for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { + // esprimo gli estremi nel riferimento della griglia + ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + // asse del cilindro + Vector3d vtV = ptP2 - ptP1 ; vtV.Normalize() ; + // calcolo box del cilindro + BBox3d BBoxCylinder ; + BBoxCylinder.Add( ptP1) ; + BBoxCylinder.Add( ptP2) ; + if ( AreSameOrOppositeVectorApprox( vtV, X_AX)) + BBoxCylinder.Expand( 0., dNewOffs, dNewOffs) ; + else if ( AreSameOrOppositeVectorApprox( vtV, Y_AX)) + BBoxCylinder.Expand( dNewOffs, 0., dNewOffs) ; + else if ( AreSameOrOppositeVectorApprox( vtV, Z_AX)) + BBoxCylinder.Expand( dNewOffs, dNewOffs, 0.) ; + else { + double dExpandX = dNewOffs * sqrt( 1 - vtV.x * vtV.x) ; + double dExpandY = dNewOffs * sqrt( 1 - vtV.y * vtV.y) ; + double dExpandZ = dNewOffs * sqrt( 1 - vtV.z * vtV.z) ; + BBoxCylinder.Expand( dExpandX, dExpandY, dExpandZ) ; + } + // determino gli intervalli di interesse mediante intersezione + int nStartI = max( 0, int( BBoxCylinder.GetMin().x / m_dStep)) ; + int nEndI = min( m_nNx[nGrid] - 1, int( BBoxCylinder.GetMax().x / m_dStep)) ; + int nStartJ = max( 0, int( BBoxCylinder.GetMin().y / m_dStep)) ; + int nEndJ = min( m_nNy[nGrid] - 1, int( BBoxCylinder.GetMax().y / m_dStep)) ; + // aggiorno gli spilloni interessati + for ( int i = nStartI ; i <= nEndI ; ++ i) { + for ( int j = nStartJ ; j <= nEndJ ; ++ j) { + // recupero il Dexel + int nPos = j * VolZMapHalfCyl.m_nNx[nGrid] + i ; + vector& vDexel = VolZMapHalfCyl.m_Values[nGrid][nPos] ; + // scorro i suoi intervalli + for ( auto& Interval : vDexel) { + // aggiungo i contributi + VolZMapHalfBorder.AddIntervalsForOffset( nGrid, i, j, Interval.dMin, Interval.dMax, + Interval.vtMinN, Interval.vtMaxN, 0, 0, true) ; + } } } - Plane3d plCut ; - if ( plCut.Set( ptP1, bMirror ? - vtPlaneN : vtPlaneN)) { - #if DEBUG - IGeoVector3d* vt = CreateGeoVector3d() ; - vt->Set( plCut.GetVersN()) ; - vt->Translate( ptP1 - ORIG) ; - VT.emplace_back( vt->Clone()) ; - VC.emplace_back( YELLOW) ; - vt->Set( plCut.GetVersN()) ; - vt->Translate( ptP2 - ORIG) ; - VT.emplace_back( vt->Clone()) ; - VC.emplace_back( YELLOW) ; - #endif - vMapVertBorders[nV1].first.emplace_back( plCut) ; - vMapVertBorders[nV2].first.emplace_back( plCut) ; - } - } - // --- se lato tra due facce definite - else { - // se non serve lo spicchio di estrusione, passo al prossimo Edge - if ( dAng * dOffs < 0.) - continue ; - // se angolo concavo, le normali vanno invertite - if ( dAng < 0.) { - vtN1.Invert() ; - vtN2.Invert() ; - } - // definisco la base dello spicchio - PolyLine PLBase ; - // recupero frame intrinseco definito dal piano della base - Frame3d frLoc ; - if ( ! frLoc.Set( ptP1, vtN1 ^ vtN2, vtN1)) - continue ; - // costruisco la base - double dPar = -1. ; - PLBase.AddUPoint( ++ dPar, ptP1) ; - CurveArc MyCrvArc ; - Point3d ptA = ptP1 + abs( dOffs) * vtN1 ; - Point3d ptC = ptP1 + abs( dOffs) * vtN2 ; - Vector3d vtTmp = vtN1 + vtN2 ; - vtTmp.Normalize() ; - vtTmp *= abs( dOffs) ; - Point3d ptB = ptP1 + vtTmp ; - MyCrvArc.Set3P( ptA, ptB, ptC) ; - PolyLine PLCrvArc ; - MyCrvArc.ApproxWithLines( 10. * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLCrvArc) ; - for ( auto& ptU : PLCrvArc.GetUPointList()) - PLBase.AddUPoint( ++ dPar, ptU.first) ; - PLBase.AddUPoint( ++ dPar, ptP1) ; - // definisco la superficie di estrusione e aggiorno gli spilloni - CurveComposite CompoBase ; - CompoBase.FromPolyLine( PLBase) ; - PtrOwner pStmClove( GetSurfTriMeshByExtrusion( &CompoBase, vtEdge, true)) ; - if ( ! IsNull( pStmClove)) { - // aggiungo gli intervalli definiti dalla superficie di estrusione - AddSurfTm( pStmClove) ; - // determino la normale del piano della curva composita definita - Plane3d PlanePL ; - double dArea ; - CompoBase.GetArea( PlanePL, dArea) ; - // per ptP1 la normale del piano di taglio deve essere come vtEdge, mentre per ptP2 opposta. - // ( In questo modo seguo l'orientamento dalla superficie di estrusione ) - Vector3d vEdgeN = vtEdge ; - vEdgeN.Normalize() ; - if ( AreSameVectorEpsilon( PlanePL.GetVersN(), vEdgeN, 50. * EPS_SMALL)) - CompoBase.Invert() ; - CompoBase.SetExtrusion( - vEdgeN) ; - // aggiungo i piani di taglio alla mappa - // --- il piano definito dalle basi dello spicchio - Plane3d plCut ; - if ( plCut.Set( ptP1, vEdgeN)) - vMapVertBorders[nV1].second.emplace_back( plCut) ; - if ( plCut.Set( ptP2, - vEdgeN)) - vMapVertBorders[nV2].second.emplace_back( plCut) ; - #if DEBUG - Point3d ptCentroid ; CompoBase.GetCentroid( ptCentroid) ; - IGeoPoint3d* pt = CreateGeoPoint3d() ; - pt->Set( ptCentroid) ; - VT.emplace_back( pt->Clone()) ; - VC.emplace_back( PURPLE) ; - IGeoVector3d* vt = CreateGeoVector3d() ; - vt->Set( vEdgeN) ; - vt->Translate( ptCentroid - ORIG) ; - VT.emplace_back( vt->Clone()) ; - VC.emplace_back( FUCHSIA) ; - pt->Translate( vEdgeN) ; - VT.emplace_back( pt->Clone()) ; - VC.emplace_back( PURPLE) ; - vt->Set( - vEdgeN) ; - vt->Translate( ( ptCentroid + vtEdge) - ORIG) ; - VT.emplace_back( vt->Clone()) ; - VC.emplace_back( FUCHSIA) ; - VT.emplace_back( CompoBase.Clone()) ; - VC.emplace_back( RED) ; - CompoBase.Translate( vtEdge) ; - VT.emplace_back( CompoBase.Clone()) ; - VC.emplace_back( RED) ; - CompoBase.Translate( - vtEdge) ; - #endif - } } + // recupero i due piani di taglio definiti + Surf->GetVertex( nV1, ptP1) ; + Surf->GetVertex( nV2, ptP2) ; + Plane3d plCut1 ; plCut1.Set( ptP1, vtEdge) ; + Plane3d plCut2 ; plCut2.Set( ptP2, - vtEdge) ; + vMapVertBorders[nV1].push_back( plCut1) ; + vMapVertBorders[nV2].push_back( plCut2) ; + vMapVertBorders[nV1].push_back( plCut) ; + vMapVertBorders[nV2].push_back( plCut) ; } - #if DEBUG - VT.emplace_back( Surf->Clone()) ; - VC.emplace_back( GREEN) ; - VT.emplace_back( this->Clone()) ; - VC.emplace_back( Color( 0., 0., 0., .5)) ; - SaveGeoObj( VT, VC, "C:\\Temp\\ZmapOffs.nge") ; - #endif - - // definisco vettore di frame Locali alle 3 griglie - FRAME3DVECTOR vFrGrid( 4) ; - vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ; - vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ; - vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ; - vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ; - - // scrorro tutti i vertici della superficie - for ( auto& Map : vMapVertBorders) { - - // recupero l'indice del vertice - int nV = Map.first ; - - // se il vertice non ha piani derivanti dalle facce, non lo considero - if ( vMapVertBorders[nV].second.empty()) - continue ; - + // ----------------------- sfere ----------------------- + for ( const int& nV : vOpenVertex) { // recupero il vertice corrente Point3d ptVertex ; Surf->GetVertex( nV, ptVertex) ; - - // definisco una sfera di raggio pari all' |Offset| con centro nel vertice + // definisco una sfera di raggio doppio rispetto all'offset con centro nel vertice VolZmap VolZMapCut ; VolZMapCut.CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0], @@ -1230,34 +1766,19 @@ VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double d // esprimo il vertice corrente nel riferimento della griglia ptVertex.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; // aggiungo il contributo degli spilloni della griglia corrente - VolZMapCut.CreateOffsetSphereOnVertex( ptVertex, abs( dOffs), nGrid) ; + VolZMapCut.CreateOffsetSphereOnVertex( ptVertex, dNewOffs, nGrid, 0) ; } - - // taglio lo Zmap con tutti i piani ricavati ( evitando quelli ripetuti ) - // --- piani di FreeEdge - for ( int i = 0 ; i < int( vMapVertBorders[nV].first.size()) ; ++ i) - VolZMapCut.CutByPlaneForOffset( vMapVertBorders[nV].first[i]) ; - // --- piani dalle facce - for ( int i = 0 ; i < int( vMapVertBorders[nV].second.size()) - 1 ; ++ i) { - bool bCut = true ; - const Plane3d& plPlaneA = vMapVertBorders[nV].second[i] ; - for ( int j = i + 1 ; bCut && j < int( vMapVertBorders[nV].second.size()) ; ++ j) { - const Plane3d& plPlaneB = vMapVertBorders[nV].second[j] ; - bCut = ( ! AreSamePlaneApprox( plPlaneA, plPlaneB)) ; - } - if ( bCut) - VolZMapCut.CutByPlaneForOffset( plPlaneA) ; - } - VolZMapCut.CutByPlaneForOffset( vMapVertBorders[nV].second.back()) ; - + // taglio lo Zmap con tutti i piani ricavati + for ( int i = 0 ; i < int( vMapVertBorders[nV].size()) ; ++ i) + VolZMapCut.CutByPlaneForOffset( vMapVertBorders[nV][i]) ; // ciclo sulle griglie Surf->GetVertex( nV, ptVertex) ; for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { // esprimo il vertice corrente nel riferimento della griglia ptVertex.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; // determino il Box della sfera posizionata su tale vertice - BBox3d BBoxSphere( ptVertex - 2. * abs( dOffs) * Vector3d( 1., 1., 1.), - ptVertex + 2. * abs( dOffs) * Vector3d( 1., 1., 1.)) ; + BBox3d BBoxSphere( ptVertex - dNewOffs * Vector3d( 1., 1., 1.), + ptVertex + dNewOffs * Vector3d( 1., 1., 1.)) ; // determino gli intervalli di interesse mediante intersezione con Box della sfera int nStartI = max( 0, int( BBoxSphere.GetMin().x / VolZMapCut.m_dStep)) ; int nEndI = min( VolZMapCut.m_nNx[nGrid] - 1, int( BBoxSphere.GetMax().x / VolZMapCut.m_dStep)) ; @@ -1271,20 +1792,50 @@ VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double d vector& vDexel = VolZMapCut.m_Values[nGrid][nPos] ; // scorro i suoi intervalli for ( auto& Interval : vDexel) { - // aggiungo i contributi - AddIntervalsForOffset( nGrid, i, j, Interval.dMin, Interval.dMax, - Interval.vtMinN, Interval.vtMaxN, 0, true) ; + VolZMapHalfBorder.AddIntervalsForOffset( nGrid, i, j, Interval.dMin, Interval.dMax, + Interval.vtMinN, Interval.vtMaxN, 0, 0, true) ; } } } } } + #if DEBUG + VT.clear() ; VC.clear() ; + VT.emplace_back( Surf->Clone()) ; + VC.emplace_back( YELLOW) ; + VT.emplace_back( VolZMapHalfBorder.Clone()) ; + VC.emplace_back( BLACK) ; + SaveGeoObj( VT, VC, "C:\\Temp\\AllStrip.nge") ; + #endif + + for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { + // aggiorno gli spilloni interessati + for ( int i = 0 ; i < m_nNx[nGrid] ; ++ i) { + for ( int j = 0 ; j < m_nNy[nGrid] ; ++ j) { + // recupero il Dexel + int nPos = j * VolZMapHalfBorder.m_nNx[nGrid] + i ; + vector& vDexel = VolZMapHalfBorder.m_Values[nGrid][nPos] ; + // scorro i suoi intervalli + for ( auto& Interval : vDexel) { + AddIntervalsForOffset( nGrid, i, j, Interval.dMin, Interval.dMax, + Interval.vtMinN, Interval.vtMaxN, 0, 0, true) ; + } + } + } + } + + #if DEBUG + VT.emplace_back( this->Clone()) ; + VC.emplace_back( WHITE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\this.nge") ; + #endif + return true ; } //---------------------------------------------------------------------------- -// [Sharped ( Chamfer/Extend )] Funzione per aggiornare mediantePrismi, Involucri concvessi +// [Sharped ( Chamfer/Extend )] Funzione per aggiornare mediantePrismi, Involucri convessi // e Facce di estrusione lo ZMap corrente mediante una superficie aperta // NB. Lo Zmap creato è orientato //---------------------------------------------------------------------------- diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index d0e3921..c15ca17 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -935,7 +935,7 @@ VolZmap::TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, con BBox3d b3Box ; if ( vtV.IsSmall()) b3Box = GetSphereMoveBBox( ptP1, ptP2, dRad) ; - else if( AreSameVectorExact( vtV2, V_NULL)) + else if ( AreSameVectorExact( vtV2, V_NULL)) b3Box = GetCylMoveBBox( ptP1, ptP2, vtV, dMaxRad, dHei) ; else b3Box = GetCylMoveRotBBox( ptP1, ptP2, vtV, vtV2, dRad, dHei) ; @@ -1385,7 +1385,7 @@ IntersLineBezierSurfSet( const Point3d& ptLineStart, const Vector3d& vtLineDir, if ( vInterv.size() == 0) bIntersVol = true ; - if( bIntersVol) { + if ( bIntersVol) { // interseco con le bezier for ( int s = 0 ; s < int( vSurfBez.size()) ; ++s) { // se ho già trovato l'intersezione con questa superficie vado avanti @@ -2699,7 +2699,7 @@ VolZmap::CylBall_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, double dMaxStemZ = max( max( ptS.z, ptTStemS.z), max( ptE.z, ptTStemE.z)) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { - for( int j = nStartJ ; j <= nEndJ ; ++ j) { + for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptSxy ; @@ -2769,7 +2769,7 @@ VolZmap::CylBall_ZPerp( int nGrid, const Point3d& ptS, const Point3d& ptE, const vtV2.Rotate( Z_AX, 0, 1) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { - for( int j = nStartJ ; j <= nEndJ ; ++ j) { + for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; @@ -3189,7 +3189,7 @@ VolZmap::Conus_ZPerp( int nGrid, const Point3d & ptS, const Point3d & ptE, const Point3d ptVE = ptE - vtToolDir * ( dStemHeigth + dL) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { - for( int j = nStartJ ; j <= nEndJ ; ++ j) { + for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; @@ -3316,7 +3316,7 @@ VolZmap::Conus_ZPerp( int nGrid, const Point3d & ptS, const Point3d & ptE, const Point3d ptVE = ptE - vtToolDir * ( CurrTool.GetHeigth() - dL) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { - for( int j = nStartJ ; j <= nEndJ ; ++ j) { + for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;