Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5897b93ab8 | |||
| 1f79def16c | |||
| a4f0a43273 |
@@ -31,7 +31,7 @@ bool
|
|||||||
CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, const ISurfTriMesh& Stm, double dSafeDist)
|
CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, const ISurfTriMesh& Stm, double dSafeDist)
|
||||||
{
|
{
|
||||||
// Il cilindro deve essere ben definito
|
// Il cilindro deve essere ben definito
|
||||||
if ( dR < EPS_SMALL || abs( dH) < EPS_SMALL)
|
if ( dR < EPS_SMALL || dH < EPS_SMALL)
|
||||||
return true ;
|
return true ;
|
||||||
// Se superficie non valida o aperta, non ha senso proseguire
|
// Se superficie non valida o aperta, non ha senso proseguire
|
||||||
if ( ! Stm.IsValid() || ! Stm.IsClosed())
|
if ( ! Stm.IsValid() || ! Stm.IsClosed())
|
||||||
@@ -81,7 +81,7 @@ bool
|
|||||||
TestCylSurfTm( const Frame3d& frCyl, double dR, double dH, const ISurfTriMesh& Stm, double dSafeDist)
|
TestCylSurfTm( const Frame3d& frCyl, double dR, double dH, const ISurfTriMesh& Stm, double dSafeDist)
|
||||||
{
|
{
|
||||||
// Il cilindro deve essere ben definito
|
// Il cilindro deve essere ben definito
|
||||||
if ( dR < EPS_SMALL || abs( dH) < EPS_SMALL)
|
if ( dR < EPS_SMALL || dH < EPS_SMALL)
|
||||||
return true ;
|
return true ;
|
||||||
// Se superficie non valida, non ha senso proseguire
|
// Se superficie non valida, non ha senso proseguire
|
||||||
if ( ! Stm.IsValid())
|
if ( ! Stm.IsValid())
|
||||||
|
|||||||
+612
-1175
File diff suppressed because it is too large
Load Diff
+2
-31
@@ -41,7 +41,7 @@ GEOOBJ_REGISTER( CRV_ARC, NGE_C_ARC, CurveArc) ;
|
|||||||
class ArcApproxer
|
class ArcApproxer
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc, double dMaxLen = INFINITO) ;
|
ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc) ;
|
||||||
bool GetPoint( double& dU, Point3d& ptP) ;
|
bool GetPoint( double& dU, Point3d& ptP) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
@@ -1177,30 +1177,6 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLin
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
CurveArc::ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const
|
|
||||||
{
|
|
||||||
// pulisco la polilinea
|
|
||||||
PL.Clear() ;
|
|
||||||
|
|
||||||
// la curva deve essere validata
|
|
||||||
if ( m_nStatus != OK)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// eseguo approssimazione
|
|
||||||
bool bInside = true ;
|
|
||||||
ArcApproxer aAppr( dLinTol, dAngTolDeg, bInside, *this, dMaxLen) ;
|
|
||||||
double dU ;
|
|
||||||
Point3d ptPos ;
|
|
||||||
while ( aAppr.GetPoint( dU, ptPos)) {
|
|
||||||
if ( ! PL.AddUPoint( dU, ptPos))
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
CurveArc::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
CurveArc::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
||||||
@@ -2194,7 +2170,7 @@ CurveArc::Flip( void)
|
|||||||
// usando il versore medio dal centro e moltiplicandolo per il coefficiente ( 2 / ( 1 + cosA)).
|
// usando il versore medio dal centro e moltiplicandolo per il coefficiente ( 2 / ( 1 + cosA)).
|
||||||
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
|
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc, double dMaxLen)
|
ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc)
|
||||||
{
|
{
|
||||||
// inizializzazioni
|
// inizializzazioni
|
||||||
m_nTotPnt = 0 ;
|
m_nTotPnt = 0 ;
|
||||||
@@ -2219,11 +2195,6 @@ ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const
|
|||||||
dAngStepDeg = sqrt( 8 * dLinTolRel) * RADTODEG ;
|
dAngStepDeg = sqrt( 8 * dLinTolRel) * RADTODEG ;
|
||||||
else
|
else
|
||||||
dAngStepDeg = sqrt( 8 * dLinTolRel / ( 1 + dLinTolRel)) * RADTODEG ;
|
dAngStepDeg = sqrt( 8 * dLinTolRel / ( 1 + dLinTolRel)) * RADTODEG ;
|
||||||
|
|
||||||
if ( dMaxLen < INFINITO) {
|
|
||||||
double dAngStepMaxLen = 2 * asin( dMaxLen / ( 2 * arArc.GetRadius())) * RADTODEG ;
|
|
||||||
dAngStepDeg = min( dAngStepDeg, dAngStepMaxLen) ;
|
|
||||||
}
|
|
||||||
dAngStepDeg = min( dAngStepDeg, dAngTolDeg) ;
|
dAngStepDeg = min( dAngStepDeg, dAngTolDeg) ;
|
||||||
|
|
||||||
// dall'angolo al centro ricavo il numero di passi
|
// dall'angolo al centro ricavo il numero di passi
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
|||||||
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
||||||
{ return CurveGetArea( *this, plPlane, dArea) ; }
|
{ return CurveGetArea( *this, plPlane, dArea) ; }
|
||||||
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||||
bool ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const override ;
|
|
||||||
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
||||||
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override
|
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override
|
||||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||||
|
|||||||
+16
-49
@@ -2652,7 +2652,7 @@ ResetCurveVoronoi( const ICurve& crvC)
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert, bool bHaltOnFork)
|
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
|
||||||
{
|
{
|
||||||
if ( ssize( vCrv) == 1)
|
if ( ssize( vCrv) == 1)
|
||||||
return true ;
|
return true ;
|
||||||
@@ -2670,7 +2670,7 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert,
|
|||||||
}
|
}
|
||||||
INTVECTOR vIds ;
|
INTVECTOR vIds ;
|
||||||
Point3d ptStart = ORIG ;
|
Point3d ptStart = ORIG ;
|
||||||
while ( chainCrv.GetChainFromNear( ptStart, bHaltOnFork, vIds)) {
|
while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) {
|
||||||
int nFirst = vIds[0] ;
|
int nFirst = vIds[0] ;
|
||||||
bool bInvert = false ;
|
bool bInvert = false ;
|
||||||
if ( nFirst < 0)
|
if ( nFirst < 0)
|
||||||
@@ -2703,18 +2703,6 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert,
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
double
|
|
||||||
CalcWeightVal( double dLen, const ICurve* pCrv, const Vector3d vtCurr1, const Point3d& ptCurr1, double dCoeff, double dMyDist, double& dUStep2)
|
|
||||||
{
|
|
||||||
pCrv->GetParamAtLength( dLen, dUStep2) ;
|
|
||||||
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
|
||||||
pCrv->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
|
||||||
double dStepCos2 = vtCurr1 * vtStep2 ;
|
|
||||||
double dDist = Dist( ptCurr1, ptStep2) ;
|
|
||||||
return (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
|
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
|
||||||
@@ -2802,11 +2790,6 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub
|
|||||||
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
|
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
|
||||||
double dSearchLen = dMyDist / 2 ;
|
double dSearchLen = dMyDist / 2 ;
|
||||||
int NUM_STEP = 10 ;
|
int NUM_STEP = 10 ;
|
||||||
const double dCoeff = 0.1 ;
|
|
||||||
double dCos = vtCurr1 * vtCurr2 ;
|
|
||||||
double dDistCurr = Dist( ptCurr1, ptCurr2) ;
|
|
||||||
double dMin = (1 - dCos) + dCoeff * dDistCurr / dMyDist ;
|
|
||||||
double bUpdated = false ;
|
|
||||||
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
|
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
|
||||||
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
|
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
|
||||||
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
||||||
@@ -2817,41 +2800,25 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub
|
|||||||
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
||||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
|
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
|
||||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
|
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
|
||||||
|
// [Controllo migliorabile, magari mendiante metodo di bisezione (?)]
|
||||||
// faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi
|
|
||||||
DBLVECTOR vVal ;
|
double dMin = INFINITO ;
|
||||||
|
const double dCoeff = 0.1 ;
|
||||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||||
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
|
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
|
||||||
double dUStep2 ;
|
double dUStep2 ; pCrvEdge2->GetParamAtLength( dLen, dUStep2) ;
|
||||||
vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ;
|
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
||||||
if ( vVal.back() < dMin) {
|
pCrvEdge2->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
||||||
dMin = vVal.back() ;
|
double dStepCos2 = vtCurr1 * vtStep2 ;
|
||||||
|
double dDist = Dist( ptCurr1, ptCurr2) ;
|
||||||
|
double dVal = (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
|
||||||
|
if ( dVal < dMin) {
|
||||||
|
ptCurr2 = ptStep2 ;
|
||||||
|
vtCurr2 = vtStep2 ;
|
||||||
dUCurr2 = dUStep2 ;
|
dUCurr2 = dUStep2 ;
|
||||||
}
|
dMin = dVal ;
|
||||||
}
|
|
||||||
DBLDBLVECTOR vInterv ;
|
|
||||||
for ( int i = 1 ; i < ssize(vVal) - 1 ; ++i) {
|
|
||||||
if ( vVal[i] < vVal[i-1] && vVal[i] < vVal[i+1])
|
|
||||||
vInterv.emplace_back( dLimInfLen2 + ( i - 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP,
|
|
||||||
dLimInfLen2 + ( i + 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP) ;
|
|
||||||
}
|
|
||||||
if ( ssize( vInterv) != 0) {
|
|
||||||
for ( int j = 0 ; j < ssize( vInterv) ; ++j) {
|
|
||||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
|
||||||
double dLen = vInterv[j].first + i * ( vInterv[j].second - vInterv[j].first) / NUM_STEP ;
|
|
||||||
double dUStep2 ;
|
|
||||||
double dVal = CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2) ;
|
|
||||||
if ( dVal < dMin) {
|
|
||||||
dUCurr2 = dUStep2 ;
|
|
||||||
dMin = dVal ;
|
|
||||||
bUpdated = true ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita
|
|
||||||
if ( bUpdated)
|
|
||||||
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
+2
-1
@@ -34,4 +34,5 @@ bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szN
|
|||||||
bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||||
|
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||||
+4
-54
@@ -1432,7 +1432,7 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, Poly
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd,
|
CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd,
|
||||||
double dLinTol, double dAngTolDeg, PolyLine& PL, double dMaxLen) const
|
double dLinTol, double dAngTolDeg, PolyLine& PL) const
|
||||||
{
|
{
|
||||||
// se raggiunto il massimo livello di recursione ...
|
// se raggiunto il massimo livello di recursione ...
|
||||||
const int MAX_LEV = 10 ;
|
const int MAX_LEV = 10 ;
|
||||||
@@ -1461,10 +1461,7 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// se distanza entro tolleranza
|
// se distanza entro tolleranza
|
||||||
bool bSplit = dMaxSqDist > ( dLinTol * dLinTol) ;
|
if ( dMaxSqDist <= ( dLinTol * dLinTol)) {
|
||||||
if ( dMaxLen < INFINITO)
|
|
||||||
bSplit = bSplit || Dist( crvBez.m_vPtCtrl[0], crvBez.m_vPtCtrl[m_nDeg]) > dMaxLen ;
|
|
||||||
if ( ! bSplit) {
|
|
||||||
// deviazione angolare tra primo e ultimo tratto del poligono di controllo (grado >= 1)
|
// deviazione angolare tra primo e ultimo tratto del poligono di controllo (grado >= 1)
|
||||||
Vector3d vtDirI = crvBez.m_vPtCtrl[1] - crvBez.m_vPtCtrl[0] ;
|
Vector3d vtDirI = crvBez.m_vPtCtrl[1] - crvBez.m_vPtCtrl[0] ;
|
||||||
Vector3d vtDirF = crvBez.m_vPtCtrl[m_nDeg] - crvBez.m_vPtCtrl[m_nDeg-1] ;
|
Vector3d vtDirF = crvBez.m_vPtCtrl[m_nDeg] - crvBez.m_vPtCtrl[m_nDeg-1] ;
|
||||||
@@ -1498,65 +1495,18 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart,
|
|||||||
// prima metà
|
// prima metà
|
||||||
crvBez1 = crvBez ;
|
crvBez1 = crvBez ;
|
||||||
crvBez1.TrimEndAtParam( dParDiv) ;
|
crvBez1.TrimEndAtParam( dParDiv) ;
|
||||||
if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL, dMaxLen))
|
if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL))
|
||||||
return false ;
|
return false ;
|
||||||
// seconda metà
|
// seconda metà
|
||||||
crvBez1 = crvBez ;
|
crvBez1 = crvBez ;
|
||||||
crvBez1.TrimStartAtParam( dParDiv) ;
|
crvBez1.TrimStartAtParam( dParDiv) ;
|
||||||
if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL, dMaxLen))
|
if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL))
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
CurveBezier::ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const
|
|
||||||
{
|
|
||||||
// pulisco la polilinea
|
|
||||||
PL.Clear() ;
|
|
||||||
|
|
||||||
// la curva deve essere validata
|
|
||||||
if ( m_nStatus != OK)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// se di primo grado, basta inserire gli estremi
|
|
||||||
if ( m_nDeg == 1) {
|
|
||||||
PL.AddUPoint( 0, m_vPtCtrl[0]) ;
|
|
||||||
PL.AddUPoint( 1, m_vPtCtrl[m_nDeg]) ;
|
|
||||||
PL.AdjustForMaxSegmentLen( dMaxLen) ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// limiti minimi su tolleranza e deviazione angolare
|
|
||||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
|
||||||
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
|
|
||||||
|
|
||||||
// inserisco il punto iniziale
|
|
||||||
if ( ! PL.AddUPoint( 0, m_vPtCtrl[0]))
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// verifico se va divisa
|
|
||||||
if ( ! FlatOrSplit( 0, *this, 0, 1, dLinTol, dAngTolDeg, PL, dMaxLen))
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// se è stato inserito un solo punto, aggiungo il finale
|
|
||||||
if ( PL.GetPointNbr() == 1)
|
|
||||||
return PL.AddUPoint( 1, m_vPtCtrl[m_nDeg]) ;
|
|
||||||
// altrimenti, se l'ultimo punto non coincide con il finale lo sostituisco (distano al max di dLinTol)
|
|
||||||
else {
|
|
||||||
Point3d ptLast ;
|
|
||||||
PL.GetLastPoint( ptLast) ;
|
|
||||||
if ( ! AreSamePointApprox( ptLast, m_vPtCtrl[m_nDeg])) {
|
|
||||||
PL.EraseLastUPoint() ;
|
|
||||||
return PL.AddUPoint( 1, m_vPtCtrl[m_nDeg]) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
CurveBezier::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
CurveBezier::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
||||||
|
|||||||
+1
-2
@@ -111,7 +111,6 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
|||||||
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
||||||
{ return CurveGetArea( *this, plPlane, dArea) ; }
|
{ return CurveGetArea( *this, plPlane, dArea) ; }
|
||||||
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||||
bool ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const override ;
|
|
||||||
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
||||||
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override
|
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override
|
||||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||||
@@ -189,7 +188,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
|||||||
bool GetSegmentParam( double dLen, double& dCurrLen, double& dSegLen,
|
bool GetSegmentParam( double dLen, double& dCurrLen, double& dSegLen,
|
||||||
double& dUIni, double& dUFin) const ;
|
double& dUIni, double& dUFin) const ;
|
||||||
bool FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd,
|
bool FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd,
|
||||||
double dLinTol, double dAngTolDeg, PolyLine& PL, double dMaxLen = INFINITO) const ;
|
double dLinTol, double dAngTolDeg, PolyLine& PL) const ;
|
||||||
bool ApproxWithArcsXY(double dLinTol, double dAngTolDeg, PolyArc& PA) const;
|
bool ApproxWithArcsXY(double dLinTol, double dAngTolDeg, PolyArc& PA) const;
|
||||||
bool BiArcOrSplit(int nLev, PolyLine& PL, double dLinTol, double dAngTolDeg, PolyArc& PA) const;
|
bool BiArcOrSplit(int nLev, PolyLine& PL, double dLinTol, double dAngTolDeg, PolyArc& PA) const;
|
||||||
bool ToPowerBase( PolynomialPoint3d& pol3P) const ;
|
bool ToPowerBase( PolynomialPoint3d& pol3P) const ;
|
||||||
|
|||||||
@@ -1460,68 +1460,6 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
|
|||||||
return PL.RemoveAlignedPoints( dLinTol) ;
|
return PL.RemoveAlignedPoints( dLinTol) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
CurveComposite::ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const
|
|
||||||
{
|
|
||||||
// funziona solo con le modalità standard e special
|
|
||||||
if ( nType != APL_STD && nType != APL_SPECIAL && nType != APL_SPECIAL_INT)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// pulisco la polilinea
|
|
||||||
PL.Clear() ;
|
|
||||||
|
|
||||||
// verifico lo stato
|
|
||||||
if ( m_nStatus != OK)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// limiti minimi su tolleranza e deviazione angolare
|
|
||||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
|
||||||
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
|
|
||||||
|
|
||||||
// se speciale, approssimo ogni singola entità e conservo le estremità interne (joint)
|
|
||||||
if ( nType == APL_SPECIAL || nType == APL_SPECIAL_INT) {
|
|
||||||
// eseguo approssimazione
|
|
||||||
double dStartPar = 0 ;
|
|
||||||
for ( auto& pCrv : m_CrvSmplS) {
|
|
||||||
// assegno estrusione e spessore della curva composita
|
|
||||||
pCrv->SetExtrusion( m_VtExtr) ;
|
|
||||||
pCrv->SetThickness( m_dThick) ;
|
|
||||||
// recupero approssimazione per curva semplice
|
|
||||||
PolyLine PLSmpl ;
|
|
||||||
if ( ! pCrv->ApproxWithLimitedLines( dLinTol, dAngTolDeg, nType, dMaxLen, PLSmpl))
|
|
||||||
return false ;
|
|
||||||
// se richiesto almeno un punto interno con curve non rettilinee e ci sono solo gli estremi
|
|
||||||
if ( nType == APL_SPECIAL_INT && pCrv->GetType() != CRV_LINE && PLSmpl.GetPointNbr() == 2) {
|
|
||||||
// aggiungo il punto interno
|
|
||||||
Point3d ptMid ;
|
|
||||||
if ( ! pCrv->GetMidPoint( ptMid))
|
|
||||||
return false ;
|
|
||||||
double dU ;
|
|
||||||
PLSmpl.GetLastU( dU) ;
|
|
||||||
dU /= 2 ;
|
|
||||||
PNTULIST& List = PLSmpl.GetUPointList() ;
|
|
||||||
List.insert( ++ List.begin(), { ptMid, dU}) ;
|
|
||||||
}
|
|
||||||
// ripristino estrusione e spessore della curva semplice (annullandoli)
|
|
||||||
pCrv->SetExtrusion( V_NULL) ;
|
|
||||||
pCrv->SetThickness( 0) ;
|
|
||||||
// la accodo opportunamente a quella della curva composita
|
|
||||||
if ( ! PL.Join( PLSmpl, dStartPar))
|
|
||||||
return false ;
|
|
||||||
// incremento inizio parametro per prossima curva semplice
|
|
||||||
dStartPar += 1 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( nType == APL_STD) {
|
|
||||||
if ( ! ApproxWithLimitedLines( dLinTol, dAngTolDeg, APL_SPECIAL, dMaxLen, PL))
|
|
||||||
return false ;
|
|
||||||
PL.RemoveAlignedPoints( dLinTol, false, dMaxLen) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
|||||||
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
||||||
{ return CurveGetArea( *this, plPlane, dArea) ; }
|
{ return CurveGetArea( *this, plPlane, dArea) ; }
|
||||||
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||||
bool ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const override ;
|
|
||||||
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
||||||
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override ;
|
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override ;
|
||||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||||
|
|||||||
@@ -514,34 +514,6 @@ CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLi
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
CurveLine::ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const
|
|
||||||
{
|
|
||||||
// pulisco la polilinea
|
|
||||||
PL.Clear() ;
|
|
||||||
|
|
||||||
// la curva deve essere validata
|
|
||||||
if ( m_nStatus != OK)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// inserisco lo start
|
|
||||||
PL.AddUPoint( 0, m_PtStart) ;
|
|
||||||
|
|
||||||
double dLen = Dist( m_PtStart, m_PtEnd) ;
|
|
||||||
if ( dLen > dMaxLen) {
|
|
||||||
int nStep = int( ceil( dLen / dMaxLen)) ;
|
|
||||||
for ( int i = 1 ; i < nStep ; ++i) {
|
|
||||||
double dPar = 1. / nStep * i ;
|
|
||||||
PL.AddUPoint( dPar, Media( m_PtStart, m_PtEnd, dPar)) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// inserisco l'end
|
|
||||||
PL.AddUPoint( 1, m_PtEnd) ;
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
CurveLine::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
CurveLine::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ class CurveLine : public ICurveLine, public IGeoObjRW
|
|||||||
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
bool GetArea( Plane3d& plPlane, double& dArea) const override
|
||||||
{ return false ; }
|
{ return false ; }
|
||||||
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||||
bool ApproxWithLimitedLines( double dLinTol, double dAngTolDeg, int nType, double dMaxLen, PolyLine& PL) const override ;
|
|
||||||
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const override ;
|
||||||
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override
|
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override
|
||||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||||
|
|||||||
Binary file not shown.
@@ -30,7 +30,7 @@
|
|||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
<UseOfMfc>false</UseOfMfc>
|
||||||
<PlatformToolset>v145</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
<UseOfMfc>false</UseOfMfc>
|
||||||
<PlatformToolset>v145</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
@@ -324,7 +324,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
|||||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||||
<ClCompile Include="OffsetCurve3d.cpp" />
|
|
||||||
<ClCompile Include="Trimming.cpp" />
|
<ClCompile Include="Trimming.cpp" />
|
||||||
<ClCompile Include="MultiGeomDB.cpp" />
|
<ClCompile Include="MultiGeomDB.cpp" />
|
||||||
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
||||||
|
|||||||
@@ -576,9 +576,6 @@
|
|||||||
<ClCompile Include="Trimming.cpp">
|
<ClCompile Include="Trimming.cpp">
|
||||||
<Filter>File di origine\GeoStriping</Filter>
|
<Filter>File di origine\GeoStriping</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="OffsetCurve3d.cpp">
|
|
||||||
<Filter>File di origine\GeoOffset</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="stdafx.h">
|
<ClInclude Include="stdafx.h">
|
||||||
|
|||||||
+43
-161
@@ -15,7 +15,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "IntersLineCyl.h"
|
#include "IntersLineCyl.h"
|
||||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||||
#include "/EgtDev/Include/EGkIntersLineCylinder.h"
|
|
||||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||||
|
|
||||||
using namespace std ;
|
using namespace std ;
|
||||||
@@ -26,176 +25,99 @@ using namespace std ;
|
|||||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
|
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
|
double dRad, double dHeight,
|
||||||
|
double& dU1, double& dU2)
|
||||||
{
|
{
|
||||||
dU1 = NAN ;
|
// Verifico il versore
|
||||||
dU2 = NAN ;
|
if ( vtL.IsSmall())
|
||||||
|
|
||||||
// Verifico il versore
|
|
||||||
if ( vtV.IsSmall())
|
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// Verifico il cilindro
|
// Verifico il cilindro
|
||||||
if ( dRad < EPS_SMALL || dH < EPS_SMALL)
|
if ( dRad < EPS_SMALL || dHeight < EPS_SMALL)
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||||
int nBasInt = 0 ;
|
int nBasInt = 0 ;
|
||||||
if ( abs( vtV.z) > EPS_ZERO) {
|
if ( abs( vtL.z) > EPS_ZERO) {
|
||||||
// le linee tangenti al cilindro non sono considerate intersecanti
|
// le linee tangenti al cilindro non sono considerate intersecanti
|
||||||
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||||
if ( bIgnoreTap)
|
Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ;
|
||||||
dEpsRad = 0. ;
|
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
|
||||||
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
|
dU1 = ( ptInt1 - ptL) * vtL ;
|
||||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
|
||||||
nBasInt += 1 ;
|
nBasInt += 1 ;
|
||||||
vtN1 = - Z_AX ;
|
|
||||||
dU1 = ( ( 0 - ptP.z) / vtV.z) ;
|
|
||||||
}
|
}
|
||||||
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
|
Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ;
|
||||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
|
||||||
|
dU2 = ( ptInt2 - ptL) * vtL ;
|
||||||
nBasInt += 2 ;
|
nBasInt += 2 ;
|
||||||
vtN2 = Z_AX ;
|
|
||||||
dU2 = ( ( dH - ptP.z) / vtV.z) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||||
if ( nBasInt == 3) {
|
if ( nBasInt == 3) {
|
||||||
if ( dU1 > dU2) {
|
if ( dU1 > dU2)
|
||||||
swap( dU1, dU2) ;
|
swap( dU1, dU2) ;
|
||||||
swap( ptInt1, ptInt2) ;
|
// Trovate intersezioni
|
||||||
swap( vtN1, vtN2) ;
|
|
||||||
}
|
|
||||||
if ( bInvertNormals) {
|
|
||||||
vtN1 *= - 1 ;
|
|
||||||
vtN2 *= - 1 ;
|
|
||||||
}
|
|
||||||
// Trovate intersezioni
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determino le intersezioni con la superficie laterale del cilindro
|
// Determino le intersezioni con la superficie laterale del cilindro
|
||||||
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
|
DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad,
|
||||||
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
|
2 * ( ptL.x * vtL.x + ptL.y * vtL.y),
|
||||||
vtV.x * vtV.x + vtV.y * vtV.y} ;
|
vtL.x * vtL.x + vtL.y * vtL.y} ;
|
||||||
DBLVECTOR vdRoots ;
|
DBLVECTOR vdRoots ;
|
||||||
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||||
|
|
||||||
// Epsilon per piani di tappo
|
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||||
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
|
|
||||||
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
|
|
||||||
if ( bIgnoreTap) {
|
|
||||||
dEpsLow = 0. ;
|
|
||||||
dEpsUp = 0. ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
|
||||||
if ( nRoot == 2) {
|
if ( nRoot == 2) {
|
||||||
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
|
double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ;
|
||||||
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
|
if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL)
|
||||||
-- nRoot ;
|
-- nRoot ;
|
||||||
}
|
}
|
||||||
if ( nRoot >= 1) {
|
if ( nRoot >= 1) {
|
||||||
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
|
double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ;
|
||||||
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
|
if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) {
|
||||||
if ( nRoot == 2)
|
if ( nRoot == 2)
|
||||||
vdRoots[0] = vdRoots[1] ;
|
vdRoots[0] = vdRoots[1] ;
|
||||||
-- nRoot ;
|
-- nRoot ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||||
if ( nRoot == 2) {
|
if ( nRoot == 2) {
|
||||||
// Punti di intersezione con la superficie del cilindro
|
|
||||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
|
||||||
ptInt2 = ptP + vdRoots[1] * vtV ;
|
|
||||||
dU1 = vdRoots[0] ;
|
dU1 = vdRoots[0] ;
|
||||||
dU2 = vdRoots[1] ;
|
dU2 = vdRoots[1] ;
|
||||||
// Determino le normali
|
if ( dU1 > dU2)
|
||||||
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
|
|
||||||
vtN1.Normalize() ;
|
|
||||||
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
|
|
||||||
vtN2.Normalize() ;
|
|
||||||
if ( dU1 > dU2) {
|
|
||||||
swap( dU1, dU2) ;
|
swap( dU1, dU2) ;
|
||||||
swap( ptInt1, ptInt2) ;
|
// Trovate intersezioni
|
||||||
swap( vtN1, vtN2) ;
|
|
||||||
}
|
|
||||||
if ( bInvertNormals) {
|
|
||||||
vtN1 *= - 1 ;
|
|
||||||
vtN2 *= - 1 ;
|
|
||||||
}
|
|
||||||
// Trovate intersezioni
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||||
else if ( nRoot == 1) {
|
else if ( nRoot == 1) {
|
||||||
// Se piano superiore
|
// Se piano superiore
|
||||||
if ( nBasInt == 2) {
|
if ( nBasInt == 2) {
|
||||||
// Punto di intersezione
|
|
||||||
dU1 = vdRoots[0] ;
|
dU1 = vdRoots[0] ;
|
||||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
|
||||||
// Normale alla superficie del cilindro verso l'interno
|
|
||||||
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
|
|
||||||
vtN1.Normalize() ;
|
|
||||||
}
|
}
|
||||||
// altrimenti piano inferiore
|
// altrimenti piano inferiore
|
||||||
else if ( nBasInt == 1) {
|
else if ( nBasInt == 1) {
|
||||||
// Punto di intersezione
|
|
||||||
dU2 = vdRoots[0] ;
|
dU2 = vdRoots[0] ;
|
||||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
|
||||||
// Normale alla superficie del cilindro verso l'interno
|
|
||||||
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
|
|
||||||
vtN2.Normalize() ;
|
|
||||||
}
|
}
|
||||||
// altrimenti niente
|
// altrimenti niente
|
||||||
else
|
else
|
||||||
return false ;
|
return false ;
|
||||||
if ( dU1 > dU2) {
|
if ( dU1 > dU2)
|
||||||
swap( dU1, dU2) ;
|
swap( dU1, dU2) ;
|
||||||
swap( ptInt1, ptInt2) ;
|
// Trovate intersezioni
|
||||||
swap( vtN1, vtN2) ;
|
|
||||||
}
|
|
||||||
if ( bInvertNormals) {
|
|
||||||
vtN1 *= - 1 ;
|
|
||||||
vtN2 *= - 1 ;
|
|
||||||
}
|
|
||||||
// Trovate intersezioni
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nessuna soluzione : nessuna intersezione
|
// Nessuna soluzione : nessuna intersezione
|
||||||
else
|
else
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
|
|
||||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
|
||||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
|
||||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
|
|
||||||
{
|
|
||||||
// Porto la linea nel riferimento del cilindro
|
|
||||||
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
|
|
||||||
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
|
|
||||||
if ( IntersLineCyl( ptP, vtV, dH, dRad, bTapLow, bTapUp,
|
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap, bInvertNormals))
|
|
||||||
{
|
|
||||||
ptInt1.ToGlob( CylFrame) ;
|
|
||||||
vtN1.ToGlob( CylFrame) ;
|
|
||||||
ptInt2.ToGlob( CylFrame) ;
|
|
||||||
vtN2.ToGlob( CylFrame) ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Linea e cilindro sono nel medesimo riferimento.
|
// Linea e cilindro sono nel medesimo riferimento.
|
||||||
// Il cilindro è definito con centro della base, asse, raggio e altezza.
|
// Il cilindro è definito con centro della base, asse, raggio e altezza.
|
||||||
@@ -211,13 +133,7 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
|||||||
if ( ! frCyl.Set( ptCyl, vtCyl))
|
if ( ! frCyl.Set( ptCyl, vtCyl))
|
||||||
return false ;
|
return false ;
|
||||||
// Ora eseguo i conti nel riferimento intrinseco
|
// Ora eseguo i conti nel riferimento intrinseco
|
||||||
bool bTapLow = false ;
|
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
|
||||||
bool bTapUp = false ;
|
|
||||||
bool bIgnoreTap = true ;
|
|
||||||
Point3d ptInt1, ptInt2 ;
|
|
||||||
Vector3d vtN1, vtN2 ;
|
|
||||||
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
|
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -228,7 +144,7 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
|||||||
bool
|
bool
|
||||||
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||||
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
||||||
double& dU1, double& dU2)
|
double& dU1, double& dU2)
|
||||||
{
|
{
|
||||||
// Determino asse ed altezza del cilindro
|
// Determino asse ed altezza del cilindro
|
||||||
Vector3d vtCyl = ptCyl2 - ptCyl1 ;
|
Vector3d vtCyl = ptCyl2 - ptCyl1 ;
|
||||||
@@ -241,39 +157,5 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
|||||||
if ( ! frCyl.Set( ptCyl1, vtCyl))
|
if ( ! frCyl.Set( ptCyl1, vtCyl))
|
||||||
return false ;
|
return false ;
|
||||||
// Ora eseguo i conti nel riferimento intrinseco
|
// Ora eseguo i conti nel riferimento intrinseco
|
||||||
bool bTapLow = false ;
|
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
|
||||||
bool bTapUp = false ;
|
|
||||||
bool bIgnoreTap = true ;
|
|
||||||
Point3d ptInt1, ptInt2 ;
|
|
||||||
Vector3d vtN1, vtN2 ;
|
|
||||||
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
|
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// linea già nel riferimento intrinseco del cilindro
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
|
||||||
double dRad, double dHeight,
|
|
||||||
double& dU1, double& dU2)
|
|
||||||
{
|
|
||||||
Point3d ptInt1, ptInt2 ;
|
|
||||||
Vector3d vtN1, vtN2 ;
|
|
||||||
bool bTapLow = false, bTapUp = false ;
|
|
||||||
bool bIgnoreTap = true ;
|
|
||||||
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp,
|
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// funzione esposta per altre dll
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
|
||||||
const Frame3d& CylFrame, double dH, double dRad,
|
|
||||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2)
|
|
||||||
{
|
|
||||||
return IntersLineCyl( ptLineSt, vtLineDir, CylFrame, dH, dRad, false, false,
|
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true, false) ;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-23
@@ -20,27 +20,17 @@
|
|||||||
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
|
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
|
||||||
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||||
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
|
double dRad, double dHeight,
|
||||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
|
double& dU1, double& dU2) ;
|
||||||
|
|
||||||
// come sopra ma passo il riferimento intrinseco del cilindro in cui portare la linea
|
|
||||||
bool
|
|
||||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
|
||||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
|
||||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
inline bool
|
inline bool
|
||||||
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||||
double dRad, double dHeight)
|
double dRad, double dHeight)
|
||||||
{
|
{
|
||||||
Point3d ptInt1, ptInt2 ;
|
|
||||||
Vector3d vtN1, vtN2 ;
|
|
||||||
double dU1, dU2 ;
|
double dU1, dU2 ;
|
||||||
bool bTapLow = false, bTapUp = false ;
|
return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ;
|
||||||
bool bIgnoreTap = true ;
|
|
||||||
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -60,12 +50,3 @@ bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
|||||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||||
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
||||||
double& dU1, double& dU2) ;
|
double& dU1, double& dU2) ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// // Linea e cilindro sono nel medesimo riferimento.
|
|
||||||
// Il cilindro è definito con raggio e altezza. ( la linea è già nel riferimento intrinseco del cilindro)
|
|
||||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
|
||||||
double dRad, double dHeight,
|
|
||||||
double& dU1, double& dU2) ;
|
|
||||||
|
|||||||
@@ -1,798 +0,0 @@
|
|||||||
//----------------------------------------------------------------------------
|
|
||||||
// EgalTech 2026
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// File : OffsetCurve3d.cpp Data : 10.06.26 Versione : 3.1f1
|
|
||||||
// Contenuto : Classe per offset di Curve 3d.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Modifiche : 10.06.26 DB Creazione modulo.
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//--------------------------- Include ----------------------------------------
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "GeoConst.h"
|
|
||||||
#include "CurveLine.h"
|
|
||||||
#include "CurveComposite.h"
|
|
||||||
#include "RemoveCurveDefects.h"
|
|
||||||
#include "IntersLineCyl.h"
|
|
||||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
|
||||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
|
||||||
#include "/EgtDev/Include/EGkOffsetCurve3d.h"
|
|
||||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
|
||||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using namespace std ;
|
|
||||||
|
|
||||||
#define SAVECRVORIG 0
|
|
||||||
#define SAVEOFFDIR 0
|
|
||||||
#define SAVECYL 0
|
|
||||||
#define SAVEOFFSET 0
|
|
||||||
#if SAVECRVORIG || SAVEOFFDIR || SAVECYL || SAVEOFFSET
|
|
||||||
#include "/EgtDev/Include/EGkColor.h"
|
|
||||||
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
||||||
vector<IGeoObj*> vGeo ;
|
|
||||||
vector<Color> vCol ;
|
|
||||||
#include "CurveArc.h"
|
|
||||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
|
||||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
OffsetCurve3d::~OffsetCurve3d( void)
|
|
||||||
{
|
|
||||||
Reset() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
OffsetCurve3d::Reset( void)
|
|
||||||
{
|
|
||||||
for ( auto& pCrv : m_CrvLst) {
|
|
||||||
if ( pCrv != nullptr) {
|
|
||||||
delete pCrv ;
|
|
||||||
pCrv = nullptr ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_CrvLst.clear() ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
OffsetCurve3d::Make( const PNT5AXVECTOR& vPnt5Ax, double dOffDist, int nType)
|
|
||||||
{
|
|
||||||
// la funzione è pensata per lavorare con il risultato dell'operazione ProjectCurveOnSurf
|
|
||||||
|
|
||||||
// vOffDir devono essere normalizzati
|
|
||||||
// mi aspetto che siano più o meno perpendicolari alla curva
|
|
||||||
|
|
||||||
// pulisco tutto
|
|
||||||
Reset() ;
|
|
||||||
|
|
||||||
INTVECTOR vFlag ;
|
|
||||||
VCT3DVECTOR vOffDir ;
|
|
||||||
PolyLine PL ;
|
|
||||||
for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) {
|
|
||||||
PL.AddUPoint( i, vPnt5Ax[i].ptP) ;
|
|
||||||
vOffDir.push_back( vPnt5Ax[i].vtDir1) ;
|
|
||||||
if ( vPnt5Ax[i].nFlag > 0)
|
|
||||||
vFlag.push_back( vPnt5Ax[i].nFlag) ;
|
|
||||||
else
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
PtrOwner<CurveComposite> pCrv( CreateBasicCurveComposite()) ;
|
|
||||||
if ( ! pCrv->FromPolyLine( PL))
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
#if SAVECRVORIG || SAVEOFFDIR
|
|
||||||
vGeo.clear() ;
|
|
||||||
vCol.clear() ;
|
|
||||||
|
|
||||||
vGeo.push_back( pCrv->Clone()) ;
|
|
||||||
vCol.push_back( AQUA) ;
|
|
||||||
#if SAVEOFFDIR
|
|
||||||
Point3d ptBase ; PL.GetFirstPoint( ptBase) ;
|
|
||||||
for ( int i = 0 ; i < ssize( vOffDir) ; ++i) {
|
|
||||||
IGeoVector3d* pVec = CreateGeoVector3d() ;
|
|
||||||
pVec->Set( vOffDir[i] * dOffDist, ptBase) ;
|
|
||||||
PL.GetNextPoint( ptBase) ;
|
|
||||||
vGeo.push_back( pVec) ;
|
|
||||||
vCol.push_back( BLUE) ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if ! SAVECYL && ! SAVEOFFSET
|
|
||||||
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// verifico se la curva è un segmento di retta
|
|
||||||
bool bIsLine = PL.GetPointNbr() == 2 ;
|
|
||||||
if ( bIsLine) {
|
|
||||||
// faccio l'offset di una linea
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// se offset nullo, copio la curva ed esco
|
|
||||||
if ( abs( dOffDist) < 10 * EPS_SMALL) {
|
|
||||||
PtrOwner<CurveComposite> pCopy( CreateBasicCurveComposite()) ;
|
|
||||||
if ( IsNull( pCopy) || ! pCopy->CopyFrom( pCrv))
|
|
||||||
return false ;
|
|
||||||
// unisco parti allineate (tranne gli estremi)
|
|
||||||
pCopy->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, false) ;
|
|
||||||
// sposto in lista
|
|
||||||
m_CrvLst.push_back( Release( pCopy)) ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bClosed = pCrv->IsClosed() ;
|
|
||||||
|
|
||||||
// identifico le zone circostanti un angolo interno
|
|
||||||
for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) {
|
|
||||||
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CONC) {
|
|
||||||
// scorro indietro e avanti flaggando i tratti da controllare
|
|
||||||
int nPrev = i - 1 ;
|
|
||||||
if ( nPrev < 0)
|
|
||||||
nPrev = ssize( vPnt5Ax) - 1;
|
|
||||||
int nNext = i + 1 ;
|
|
||||||
if ( nNext >= ssize( vPnt5Ax))
|
|
||||||
nNext = 0 ;
|
|
||||||
double dAng = acos( vPnt5Ax[nPrev].vtDir1 * vPnt5Ax[nNext].vtDir1) * RADTODEG ;
|
|
||||||
double dDistAngConc = dOffDist * tan( ( dAng / 2) * DEGTORAD) ;
|
|
||||||
int c = nPrev ;
|
|
||||||
while ( Dist( vPnt5Ax[i].ptP, vPnt5Ax[c].ptP) < dDistAngConc) {
|
|
||||||
vFlag[c] = OffsetCurve3d::AngType::ANG_BEFORE_CONC ;
|
|
||||||
--c ;
|
|
||||||
if ( c < 0) {
|
|
||||||
if ( bClosed)
|
|
||||||
c = ssize( vPnt5Ax) - 1 ;
|
|
||||||
else
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vFlag[c] = OffsetCurve3d::AngType::ANG_BEFORE_CONC ;
|
|
||||||
// scorro in avanti
|
|
||||||
c = nNext ;
|
|
||||||
while ( c < ssize( vPnt5Ax) - 1 && Dist( vPnt5Ax[i].ptP, vPnt5Ax[c].ptP) < dDistAngConc) {
|
|
||||||
vFlag[c] = OffsetCurve3d::AngType::ANG_AFTER_CONC ;
|
|
||||||
++c ;
|
|
||||||
if ( c == ssize( vPnt5Ax) - 1) {
|
|
||||||
if ( bClosed)
|
|
||||||
c = 0 ;
|
|
||||||
else
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vFlag[c] = OffsetCurve3d::AngType::ANG_AFTER_CONC ;
|
|
||||||
i = c ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int i = 1 ; i < ssize( vFlag) - 1 ; ++i) {
|
|
||||||
if ( vFlag[i-1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC &&
|
|
||||||
vFlag[i+1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC &&
|
|
||||||
vFlag[i] != OffsetCurve3d::AngType::ANG_SMOOTH_CONC)
|
|
||||||
vFlag[i] = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ;
|
|
||||||
}
|
|
||||||
|
|
||||||
double dRadCorr ;
|
|
||||||
Point3d ptPrev ; pCrv->GetStartPoint( ptPrev) ;
|
|
||||||
ptPrev += vOffDir[0] * dOffDist ;
|
|
||||||
Vector3d vtCorrPrev ;
|
|
||||||
Vector3d vtTangPrev ;
|
|
||||||
Vector3d vtDirPrev ; pCrv->GetStartDir( vtDirPrev) ;
|
|
||||||
if ( bClosed) {
|
|
||||||
Vector3d vtDirLast ; pCrv->GetEndDir( vtDirLast) ;
|
|
||||||
if ( vFlag[0] != OffsetCurve3d::AngType::ANG_CVEX)
|
|
||||||
vtTangPrev = Media( vtDirLast, vtDirPrev) ;
|
|
||||||
else if ( vFlag[0] == OffsetCurve3d::AngType::ANG_CVEX && vFlag.back() != OffsetCurve3d::AngType::ANG_CVEX)
|
|
||||||
vtTangPrev = vtDirLast ;
|
|
||||||
else
|
|
||||||
vtTangPrev = vtDirPrev ;
|
|
||||||
}
|
|
||||||
const ICurve* pCrvPrev = pCrv->GetFirstCurve() ;
|
|
||||||
const ICurve* pCrvCurr ;
|
|
||||||
OFFSETSEGVEC vOffsetCrvs ;
|
|
||||||
Vector3d vtDirPrevOff = V_INVALID ;
|
|
||||||
int nRejected = 0 ;
|
|
||||||
int nClosure = bClosed ? 1 : 0 ;
|
|
||||||
bool bCheckingClosure = false ;
|
|
||||||
bool bPlanarConcCvex = false ;
|
|
||||||
bool bPrevTwoPointsWereConvex = false ;
|
|
||||||
for ( int i = 1 ; i <= pCrv->GetCurveCount() + nClosure ; ++i) {
|
|
||||||
int nCurr = i ;
|
|
||||||
int nPrev = i - 1 ;
|
|
||||||
if ( i > pCrv->GetCurveCount()) {
|
|
||||||
nCurr = 0 ;
|
|
||||||
bCheckingClosure = true ;
|
|
||||||
}
|
|
||||||
if ( ! bCheckingClosure)
|
|
||||||
pCrvCurr = pCrv->GetNextCurve() ;
|
|
||||||
if ( pCrvCurr == nullptr && bClosed)
|
|
||||||
pCrvCurr = pCrv->GetFirstCurve() ;
|
|
||||||
Vector3d vtOffDir = vOffDir[nCurr] ;
|
|
||||||
Vector3d vtDirCurr ;
|
|
||||||
if ( pCrvCurr != nullptr)
|
|
||||||
pCrvCurr->GetStartDir( vtDirCurr) ;
|
|
||||||
else
|
|
||||||
vtDirCurr = vtDirPrev ;
|
|
||||||
pCrvPrev->GetStartDir( vtDirPrev) ;
|
|
||||||
Vector3d vtTang ;
|
|
||||||
// so che ci sono due punti in stretta prossimità dell'angolo, quindi discrimino tra la tangeten prima e dopo l'angolo
|
|
||||||
// negli altri casi faccio la media
|
|
||||||
if ( vFlag[nCurr] != OffsetCurve3d::AngType::ANG_CVEX)
|
|
||||||
vtTang = Media( vtDirCurr, vtDirPrev) ;
|
|
||||||
else if ( vFlag[nCurr] == OffsetCurve3d::AngType::ANG_CVEX && ( vFlag[nPrev] != OffsetCurve3d::AngType::ANG_CVEX || bPrevTwoPointsWereConvex))
|
|
||||||
vtTang = vtDirPrev ;
|
|
||||||
else
|
|
||||||
vtTang = vtDirCurr ;
|
|
||||||
vtTang.Normalize() ;
|
|
||||||
Vector3d vtCorr = vtOffDir ;
|
|
||||||
double dCorrK = 1 ;
|
|
||||||
//if ( vFlag[nCurr] == OffsetCurve3d::AngType::ANG_CONC) {
|
|
||||||
// double dHalfAlfa = acos( vtTang * vtTangPrev) * RADTODEG ;
|
|
||||||
// dCorrK = 1 / sin( ( 90 - dHalfAlfa) * DEGTORAD) ;
|
|
||||||
//}
|
|
||||||
|
|
||||||
Point3d ptP ;
|
|
||||||
if ( pCrvCurr != nullptr)
|
|
||||||
pCrvCurr->GetStartPoint( ptP) ;
|
|
||||||
else
|
|
||||||
pCrvPrev->GetEndPoint( ptP) ;
|
|
||||||
dRadCorr = dOffDist ;
|
|
||||||
ptP = ptP + dRadCorr * dCorrK * vtCorr ;
|
|
||||||
// se secondo punto di angolo esterno di fianco, inserisco movimenti intermedi
|
|
||||||
if ( vFlag[nCurr] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[nPrev] == OffsetCurve3d::AngType::ANG_CVEX && ! bPrevTwoPointsWereConvex && bPlanarConcCvex) {
|
|
||||||
double dAlfa = acos( vtTang * vtTangPrev) ;
|
|
||||||
double dDelta = dOffDist * tan( dAlfa / 4) ;
|
|
||||||
Point3d ptAdd1 = ptPrev + dDelta * vtTangPrev ;
|
|
||||||
ICurveLine* pCL1 = CreateBasicCurveLine() ;
|
|
||||||
pCL1->Set( ptPrev, ptAdd1) ;
|
|
||||||
vOffsetCrvs.emplace_back( pCL1, OffsetCurve3d::AngType::ANG_CVEX, -1) ;
|
|
||||||
Point3d ptAdd2 = ptP - dDelta * vtTang ;
|
|
||||||
ICurveLine* pCL2 = CreateBasicCurveLine() ;
|
|
||||||
pCL2->Set( ptAdd1, ptAdd2) ;
|
|
||||||
vOffsetCrvs.emplace_back( pCL2, OffsetCurve3d::AngType::ANG_CVEX, -1) ;
|
|
||||||
ptPrev = ptAdd2 ;
|
|
||||||
bPrevTwoPointsWereConvex = true ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
bPrevTwoPointsWereConvex = false ;
|
|
||||||
Vector3d vtAng = vtDirPrev ^ vtDirCurr ;
|
|
||||||
const double COS_ANG_MAX_PLANAR = 0.7 ;
|
|
||||||
bPlanarConcCvex = false ;
|
|
||||||
if ( ! vtAng.IsSmall() && vtAng.Normalize())
|
|
||||||
bPlanarConcCvex = abs( vtAng * vOffDir[nCurr]) < COS_ANG_MAX_PLANAR ;
|
|
||||||
|
|
||||||
if ( ! bCheckingClosure) {
|
|
||||||
Vector3d vtDirCurrOff = ptP - ptPrev ; vtDirCurrOff.Normalize() ;
|
|
||||||
double dProj = 1 ;
|
|
||||||
if ( vtDirPrevOff.IsValid())
|
|
||||||
dProj = vtDirCurrOff * vtDirPrevOff ;
|
|
||||||
// prima di inserirlo controllo che il tratto non torni indietro
|
|
||||||
if ( ( vFlag[nCurr] != ANG_STR || dProj > - 0.966) && Dist( ptPrev, ptP) > 2 * EPS_SMALL) {
|
|
||||||
// aggiungo tratto
|
|
||||||
ICurveLine* pCL = CreateBasicCurveLine() ;
|
|
||||||
pCL->Set( ptPrev, ptP) ;
|
|
||||||
vOffsetCrvs.emplace_back( pCL, vFlag[nCurr], i - 1) ;
|
|
||||||
// aggiorno punto precedente
|
|
||||||
ptPrev = ptP ;
|
|
||||||
vtCorrPrev = vtCorr ;
|
|
||||||
vtTangPrev = vtTang ;
|
|
||||||
vtDirPrev = vtDirCurr ;
|
|
||||||
if ( i < pCrv->GetCurveCount())
|
|
||||||
pCrvPrev = pCrvCurr ;
|
|
||||||
vtDirPrevOff = vtDirCurrOff ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++nRejected ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// se chiusa aggiungo il tratto di chiusura
|
|
||||||
if ( bClosed) {
|
|
||||||
Point3d ptPS ; vOffsetCrvs.front().pCrv->GetStartPoint( ptPS) ;
|
|
||||||
ICurveLine* pCL = CreateBasicCurveLine() ;
|
|
||||||
Point3d ptPE ; vOffsetCrvs.back().pCrv->GetEndPoint( ptPE) ;
|
|
||||||
pCL->Set( ptPE, ptPS) ;
|
|
||||||
// aggiungo solo se valida, quindi se non sono già coincidenti
|
|
||||||
if ( pCL->IsValid())
|
|
||||||
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// qui faccio la correzione per gli angoli interni
|
|
||||||
EDITCRVINFOVEC vEditInfo ;
|
|
||||||
if ( ! CalcAdjustConcavePartsInPath( pCrv, vOffsetCrvs, dOffDist, vEditInfo))
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
if ( nType == OFFTYPE::PLANECUT) {
|
|
||||||
if ( ! CalcAdjustConcavePartsPlaneCut( pCrv, vPnt5Ax, vOffsetCrvs, dOffDist, vEditInfo))
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// applico le modifiche calcolate
|
|
||||||
for ( int i = ssize( vEditInfo) - 1 ; i >= 0 ; --i) {
|
|
||||||
if ( vEditInfo[i].nFlag == EditCrvInfo::NOEDIT)
|
|
||||||
continue ;
|
|
||||||
else if ( vEditInfo[i].nFlag == EditCrvInfo::DEL)
|
|
||||||
vOffsetCrvs.erase( vOffsetCrvs.begin() + i) ;
|
|
||||||
else if ( vEditInfo[i].nFlag == EditCrvInfo::EDIT) {
|
|
||||||
if ( vEditInfo[i].ptStart.IsValid())
|
|
||||||
vOffsetCrvs[vEditInfo[i].nId].pCrv->ModifyStart( vEditInfo[i].ptStart) ;
|
|
||||||
if ( vEditInfo[i].ptEnd.IsValid())
|
|
||||||
vOffsetCrvs[vEditInfo[i].nId].pCrv->ModifyEnd( vEditInfo[i].ptEnd) ;
|
|
||||||
vOffsetCrvs[vEditInfo[i].nId].nParent = -2 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scorro tutto il vettore delle linee di offset e unisco aggiungendo una linea dove ne ho cancellate
|
|
||||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) - 1 ; ++i) {
|
|
||||||
Point3d ptEndCurr, ptStartNext ;
|
|
||||||
vOffsetCrvs[i].pCrv->GetEndPoint( ptEndCurr) ;
|
|
||||||
vOffsetCrvs[i+1].pCrv->GetStartPoint( ptStartNext) ;
|
|
||||||
if ( ! AreSamePointApprox( ptEndCurr, ptStartNext)) {
|
|
||||||
ICurveLine* pCL = CreateBasicCurveLine() ;
|
|
||||||
pCL->Set( ptEndCurr, ptStartNext) ;
|
|
||||||
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR,-1) ;
|
|
||||||
rotate( vOffsetCrvs.begin() + i + 1, vOffsetCrvs.end() - 1, vOffsetCrvs.end()) ;
|
|
||||||
++i ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SAVEOFFSET || SAVECYL
|
|
||||||
#if SAVEOFFSET
|
|
||||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
|
||||||
vGeo.push_back( vOffsetCrvs[i].pCrv->Clone()) ;
|
|
||||||
if ( vOffsetCrvs[i].nParent == -2)
|
|
||||||
vCol.push_back( LIME) ;
|
|
||||||
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC)
|
|
||||||
vCol.push_back( GREEN) ;
|
|
||||||
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_STR)
|
|
||||||
vCol.push_back( PURPLE) ;
|
|
||||||
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_CVEX)
|
|
||||||
vCol.push_back( RED) ;
|
|
||||||
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_BEFORE_CONC)
|
|
||||||
vCol.push_back( OLIVE) ;
|
|
||||||
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_AFTER_CONC)
|
|
||||||
vCol.push_back( YELLOW) ;
|
|
||||||
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_CONC)
|
|
||||||
vCol.push_back( Color(0,64,0)) ; //dark green
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// qua andrebbe gestito con una chain ( ptorebbero essere più di una curva)
|
|
||||||
PtrOwner<ICurveComposite> pCrvOffset( CreateBasicCurveComposite()) ;
|
|
||||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
|
||||||
if ( ! pCrvOffset->AddCurve( Release( vOffsetCrvs[i].pCrv)))
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
m_CrvLst.push_back( Release( pCrvOffset)) ;
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
|
|
||||||
// raccordi
|
|
||||||
|
|
||||||
//// ordino le curve in ordine decrescente di lunghezza
|
|
||||||
//if ( m_CrvLst.size() > 1) {
|
|
||||||
// for ( auto pCrv : m_CrvLst) {
|
|
||||||
// double dLen ;
|
|
||||||
// if ( pCrv->GetLength( dLen))
|
|
||||||
// pCrv->SetTempProp( int( 1000 * dLen)) ;
|
|
||||||
// else
|
|
||||||
// pCrv->SetTempProp( 0) ;
|
|
||||||
// }
|
|
||||||
// m_CrvLst.sort( []( const ICurve* pA, const ICurve* pB) { return ( pA->GetTempProp() > pB->GetTempProp()) ; }) ;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// se originale era chiusa, verifico le risultanti e se necessario cerco di chiuderle
|
|
||||||
//if ( bClosed) {
|
|
||||||
// for ( auto pCrv : m_CrvLst) {
|
|
||||||
// CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ;
|
|
||||||
// if ( pCrvCo != nullptr)
|
|
||||||
// pCrvCo->Close() ;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
ICurve*
|
|
||||||
OffsetCurve3d::GetCurve( void)
|
|
||||||
{
|
|
||||||
return GetLongerCurve() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
ICurve*
|
|
||||||
OffsetCurve3d::GetLongerCurve( void)
|
|
||||||
{
|
|
||||||
if ( m_CrvLst.empty())
|
|
||||||
return nullptr ;
|
|
||||||
// le curve sono ordinate in senso decrescente di lunghezza
|
|
||||||
ICurve* pCrv = m_CrvLst.front() ;
|
|
||||||
m_CrvLst.pop_front() ;
|
|
||||||
return pCrv ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
ICurve*
|
|
||||||
OffsetCurve3d::GetShorterCurve( void)
|
|
||||||
{
|
|
||||||
if ( m_CrvLst.empty())
|
|
||||||
return nullptr ;
|
|
||||||
// le curve sono ordinate in senso decrescente di lunghezza
|
|
||||||
ICurve* pCrv = m_CrvLst.back() ;
|
|
||||||
m_CrvLst.pop_back() ;
|
|
||||||
return pCrv ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
IsPointInsideCylinder( const Point3d& ptTest, const Cyl& offCyl, double dLinTol)
|
|
||||||
{
|
|
||||||
Point3d ptTestLoc = ptTest ; ptTestLoc.ToLoc( offCyl.frCyl) ;
|
|
||||||
if ( ptTestLoc.z > offCyl.dH || ptTestLoc.z < 0)
|
|
||||||
return false ;
|
|
||||||
double dDist = ptTestLoc.x * ptTestLoc.x + ptTestLoc.y * ptTestLoc.y ;
|
|
||||||
double dRadSq = ( offCyl.dRad - dLinTol) * ( offCyl.dRad - dLinTol) ;
|
|
||||||
if ( dDist > dRadSq)
|
|
||||||
return false ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
CalcAdjustConcavePartsInPath( const ICurveComposite* pCrv, const OFFSETSEGVEC& vOffsetCrvs, double dRad, EDITCRVINFOVEC& vEditInfo)
|
|
||||||
{
|
|
||||||
const double dLinTol = 0 * EPS_SMALL ;
|
|
||||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
|
||||||
int nFlag = vOffsetCrvs[i].nFlag ;
|
|
||||||
// considero tutt le zone concave
|
|
||||||
if ( nFlag >= OffsetCurve3d::AngType::ANG_CONC) {
|
|
||||||
// scorro i prossimi finchè trovo la fine della zona concava
|
|
||||||
// controllo se devo considerare anche tratti prima dello start
|
|
||||||
INTVECTOR vLines ;
|
|
||||||
if ( i == 0) {
|
|
||||||
INTVECTOR vLinesAdd ;
|
|
||||||
int c = ssize( vOffsetCrvs) - 1 ;
|
|
||||||
nFlag = vOffsetCrvs[c].nFlag ;
|
|
||||||
while ( nFlag >= OffsetCurve3d::AngType::ANG_CONC) {
|
|
||||||
vLinesAdd.push_back( c) ;
|
|
||||||
--c ;
|
|
||||||
if ( c > 0)
|
|
||||||
nFlag = vOffsetCrvs[c].nFlag ;
|
|
||||||
}
|
|
||||||
// inserisco il vettore al contrario, in modo che sia in ordine crescente
|
|
||||||
vLines.insert( vLines.end(), vLinesAdd.rbegin(), vLinesAdd.rend()) ;
|
|
||||||
}
|
|
||||||
bool bDone = false ;
|
|
||||||
nFlag = vOffsetCrvs[i].nFlag ;
|
|
||||||
while ( nFlag >= OffsetCurve3d::AngType::ANG_CONC) {
|
|
||||||
vLines.push_back( i) ;
|
|
||||||
++i ;
|
|
||||||
if ( i < ssize( vOffsetCrvs))
|
|
||||||
nFlag = vOffsetCrvs[i].nFlag ;
|
|
||||||
else {
|
|
||||||
bDone = true ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// se sto ricominciando, esco dal for ( il tratto finale è già stato considerato insieme al tratto iniziale)
|
|
||||||
if ( bDone)
|
|
||||||
break ;
|
|
||||||
CYLVECT vCyl ;
|
|
||||||
// creo un cilindro della dimensione del raggio
|
|
||||||
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
|
|
||||||
if ( vOffsetCrvs[vLines[j]].nParent == -1)
|
|
||||||
continue ;
|
|
||||||
const ICurve* pSubCrv = pCrv->GetCurve( vOffsetCrvs[vLines[j]].nParent) ;
|
|
||||||
Point3d ptStart, ptEnd ;
|
|
||||||
pSubCrv->GetStartPoint( ptStart) ;
|
|
||||||
pSubCrv->GetEndPoint( ptEnd) ;
|
|
||||||
// cilindri con asse sul parent
|
|
||||||
Vector3d vtHeight = ptEnd - ptStart ;
|
|
||||||
double dHeight = vtHeight.Len() ;
|
|
||||||
vtHeight.Normalize() ;
|
|
||||||
vCyl.emplace_back( ptStart, vtHeight, dHeight, dRad, dLinTol) ;
|
|
||||||
#if SAVECYL
|
|
||||||
CurveArc ca ; ca.Set( ptStart, vtHeight, dRad) ;
|
|
||||||
ISurfTriMesh* pSurfTm = GetSurfTriMeshByExtrusion( &ca, vtHeight * dHeight, false, 2 * EPS_SMALL) ;
|
|
||||||
vGeo.push_back( pSurfTm) ;
|
|
||||||
vCol.push_back( LGRAY) ;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// controllo l'end di ogni linea per verificare se sta nel cilindro definito da uno degli altri tratti
|
|
||||||
// controllo tutto i punti
|
|
||||||
bool bErasedSomePart = false ;
|
|
||||||
bool bCheckStart = false ;
|
|
||||||
vector<INTINTVECTOR> vEditZones ;
|
|
||||||
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
|
|
||||||
Point3d ptStart, ptEnd ;
|
|
||||||
const ICurve* pSubCrv = vOffsetCrvs[vLines[j]].pCrv ;
|
|
||||||
if ( pSubCrv == nullptr)
|
|
||||||
return false ;
|
|
||||||
pSubCrv->GetEndPoint( ptEnd) ;
|
|
||||||
pSubCrv->GetStartPoint( ptStart) ;
|
|
||||||
// se stanno in uno dei cilindri degli altri tratti della zona concava
|
|
||||||
bool bToErase = false ;
|
|
||||||
for ( int k = 0 ; k < ssize( vCyl) ; ++k) {
|
|
||||||
if ( j == k)
|
|
||||||
continue ;
|
|
||||||
bToErase = IsPointInsideCylinder( ptEnd, vCyl[k], dLinTol) ;
|
|
||||||
bool bStartInsideCyl = false ;
|
|
||||||
if ( bCheckStart && ! bToErase) {
|
|
||||||
bStartInsideCyl = IsPointInsideCylinder( ptStart, vCyl[k], dLinTol) ;
|
|
||||||
bToErase = bToErase || bStartInsideCyl ;
|
|
||||||
}
|
|
||||||
if ( bToErase) {
|
|
||||||
bErasedSomePart = true ;
|
|
||||||
if ( ! bStartInsideCyl)
|
|
||||||
bCheckStart = true ;
|
|
||||||
|
|
||||||
if ( vEditZones.empty() || vEditZones.back().back().first != vLines[j-1])
|
|
||||||
vEditZones.emplace_back() ;
|
|
||||||
vEditZones.back().emplace_back( vLines[j], j) ;
|
|
||||||
if ( ! bStartInsideCyl && j < ssize( vLines) - 1) {
|
|
||||||
vEditZones.back().emplace_back( vLines[j+1], j + 1) ;
|
|
||||||
++j ;
|
|
||||||
}
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ! bToErase) {
|
|
||||||
bCheckStart = false ;
|
|
||||||
vEditInfo.emplace_back( vLines[j], EditCrvInfo::NOEDIT) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bErasedSomePart) {
|
|
||||||
// calcolo le intersezioni effettive del primo e ultimo tratto cancellati con i cilindri che li hanno cancellati
|
|
||||||
for ( int z = 0 ; z < ssize( vEditZones) ; ++z) {
|
|
||||||
INTINTVECTOR& vInters = vEditZones[z] ;
|
|
||||||
if ( ssize( vInters) == 1)
|
|
||||||
continue ;
|
|
||||||
for ( int j = 0 ; j < ssize( vInters) ; ++j) {
|
|
||||||
// cancello i tratti intermedi
|
|
||||||
if ( j > 0 && j < ssize( vInters) - 1) {
|
|
||||||
vEditInfo.emplace_back( vInters[j].first, EditCrvInfo::DEL) ;
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
// per il primo e ultimo controllo le intersezioni con tutti i cilindri
|
|
||||||
PtrOwner<ICurve> pCL ( vOffsetCrvs[vInters[j].first].pCrv->Clone()) ;
|
|
||||||
Point3d ptStart ; pCL->GetStartPoint( ptStart) ;
|
|
||||||
Vector3d vtStart ; pCL->GetStartDir( vtStart) ;
|
|
||||||
double dLen ; pCL->GetLength( dLen) ;
|
|
||||||
double dUTrim = ( j == 0 ? INFINITO : 0) ;
|
|
||||||
Point3d ptTrim = P_INVALID ;
|
|
||||||
for ( int k = 0 ; k < ssize( vCyl) ; ++k) {
|
|
||||||
if ( vInters[j].second == k)
|
|
||||||
continue ;
|
|
||||||
Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
|
|
||||||
double dU1, dU2 ;
|
|
||||||
Vector3d vtN1, vtN2 ;
|
|
||||||
if ( IntersLineCyl( ptStart, vtStart * dLen, vCyl[k].frCyl, vCyl[k].dH, vCyl[k].dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true)) {
|
|
||||||
bool bUpdate = ( j == 0 ? dU1 < dUTrim : dU1 > dUTrim) ;
|
|
||||||
bUpdate = bUpdate && ptInt1.IsValid() && dU1 > 0 && dU1 < 1 ;
|
|
||||||
bUpdate = bUpdate && vtN1 * vtStart < 0 ;
|
|
||||||
if ( bUpdate) {
|
|
||||||
dUTrim = dU1 ;
|
|
||||||
ptTrim = ptInt1 ;
|
|
||||||
}
|
|
||||||
bUpdate = ( j == 0 ? dU2 < dUTrim : dU2 > dUTrim) ;
|
|
||||||
bUpdate = bUpdate && ptInt2.IsValid() && dU2 > 0 && dU2 < 1 ;
|
|
||||||
bUpdate = bUpdate && vtN2 * vtStart > 0 ;
|
|
||||||
if ( bUpdate) {
|
|
||||||
dUTrim = dU2 ;
|
|
||||||
ptTrim = ptInt2 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( j == 0) {
|
|
||||||
if ( ptTrim.IsValid()) {
|
|
||||||
bool bOk = pCL->ModifyEnd( ptTrim) ;
|
|
||||||
double dNewLen ;
|
|
||||||
if ( bOk)
|
|
||||||
pCL->GetLength( dNewLen) ;
|
|
||||||
if ( ( ! bOk || dNewLen < 0.1) && vInters[0].first != 0) { // se fosse il primo allora potrei modificare il successivo
|
|
||||||
int nPrev = vInters[0].first - 1 ;
|
|
||||||
vInters[0].first = nPrev ;
|
|
||||||
int c = 1 ;
|
|
||||||
while( vEditInfo.end()[-c].nId != nPrev)
|
|
||||||
++c ;
|
|
||||||
vEditInfo.end()[-c].nFlag = EditCrvInfo::EDIT ;
|
|
||||||
vEditInfo.end()[-c].ptEnd = ptTrim ;
|
|
||||||
vEditInfo.emplace_back( nPrev + 1, EditCrvInfo::DEL) ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vEditInfo.emplace_back( vInters[0].first, EditCrvInfo::EDIT, P_INVALID, ptTrim) ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vEditInfo.emplace_back( vInters[0].first, EditCrvInfo::EDIT, P_INVALID, P_INVALID) ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( ptTrim.IsValid()) {
|
|
||||||
bool bOk = pCL->ModifyStart( ptTrim) ;
|
|
||||||
double dNewLen ;
|
|
||||||
if ( bOk)
|
|
||||||
pCL->GetLength( dNewLen) ;
|
|
||||||
if ( ( ! bOk || dNewLen < 0.1) && vInters[j].first != ssize( vOffsetCrvs) - 1) { // se fosse l'ultima curva allora potrei modificare la precedente
|
|
||||||
int nNext = vInters[j].first + 1 ;
|
|
||||||
vInters[j].first = nNext ;
|
|
||||||
vEditInfo.emplace_back( nNext - 1, EditCrvInfo::DEL) ;
|
|
||||||
int c = 1 ;
|
|
||||||
while ( vEditInfo.end()[-c].nId != nNext && c < ssize( vEditInfo))
|
|
||||||
++c ;
|
|
||||||
if ( vEditInfo.end()[-c].nId == nNext) {
|
|
||||||
vEditInfo.end()[-c].nFlag = EditCrvInfo::EDIT ;
|
|
||||||
vEditInfo.end()[-c].ptStart = ptTrim ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vEditInfo.emplace_back( nNext, EditCrvInfo::EDIT, ptTrim, P_INVALID) ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vEditInfo.emplace_back( vInters[j].first, EditCrvInfo::EDIT, ptTrim, P_INVALID) ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vEditInfo.emplace_back( vInters[j].first, EditCrvInfo::EDIT, P_INVALID, P_INVALID) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = vLines.back() ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( vEditInfo.empty() || vEditInfo.back().nId != i)
|
|
||||||
vEditInfo.emplace_back( i, EditCrvInfo::NOEDIT) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort( vEditInfo.begin(), vEditInfo.end(), []( EditCrvInfo& a, EditCrvInfo& b) { return a.nId < b.nId ;}) ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
CalcAdjustConcavePartsPlaneCut( const ICurveComposite* pCrv, const PNT5AXVECTOR& vPnt5Ax, const OFFSETSEGVEC& vOffsetCrvs,
|
|
||||||
double dRad, EDITCRVINFOVEC& vEditInfo)
|
|
||||||
{
|
|
||||||
// calcolo come tagliare il percorso negli angoli misti concavo/convesso
|
|
||||||
// il taglio al percorso lo faccio usando il piano definito dalla direzione di offset
|
|
||||||
// se una delle due direzioni è perpendicolare al piano formato dai due tratti, la cui joint è il punto corrente, allora non faccio nulla
|
|
||||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
|
||||||
if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_CVEX) {
|
|
||||||
// se ho 2 tratti convex di fila, ho un convex non planar e se ho anche un angolo importante tra i due lati, devo correggere
|
|
||||||
// se ho 4 tratti convex di fila, ho un convex planar e non devo fare nulla
|
|
||||||
int c = 1 ;
|
|
||||||
while ( i + c < ssize( vOffsetCrvs) && vOffsetCrvs[i + c].nFlag == OffsetCurve3d::AngType::ANG_CVEX)
|
|
||||||
++c ;
|
|
||||||
if ( c == 4) {
|
|
||||||
i += 3 ;
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trovo i due piani e taglio i tratti prima e dopo lo spigolo
|
|
||||||
int nParent = vOffsetCrvs[i].nParent ; // sottocurva di pCrv che ha generato il tratto di offset
|
|
||||||
Point3d pt ; pCrv->GetCurve( nParent)->GetEndPoint( pt) ;
|
|
||||||
int nNextParent = nParent + 1 ;
|
|
||||||
bool bCheckingStart = false ;
|
|
||||||
if ( nNextParent > pCrv->GetCurveCount() - 1) {
|
|
||||||
if ( ! pCrv->IsClosed())
|
|
||||||
return false ;
|
|
||||||
nNextParent = 0 ;
|
|
||||||
bCheckingStart = true ;
|
|
||||||
}
|
|
||||||
Vector3d vtDirNext ; pCrv->GetCurve( nNextParent)-> GetStartDir( vtDirNext) ;
|
|
||||||
Vector3d vtDirPrev ; pCrv->GetCurve( nParent)-> GetEndDir( vtDirPrev) ;
|
|
||||||
// punti che rappresentano la pCrv ( quindi pCrv->GetCurveCount() == ssize( vPnt5Ax) - 1)
|
|
||||||
Vector3d vtNNext ;
|
|
||||||
Vector3d vtNPrev ;
|
|
||||||
if ( ! bCheckingStart) {
|
|
||||||
vtNNext = vPnt5Ax[nNextParent].vtDir2 ^ vtDirNext ;
|
|
||||||
vtNPrev = vPnt5Ax[nNextParent].vtDir1 ^ vtDirPrev ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vtNNext = vPnt5Ax[nNextParent].vtDir1 ^ vtDirNext ;
|
|
||||||
vtNPrev = vPnt5Ax[nNextParent].vtDir2 ^ vtDirPrev ;
|
|
||||||
}
|
|
||||||
Plane3d plNext ; plNext.Set( pt, vtNNext) ;
|
|
||||||
Plane3d plPrev ; plPrev.Set( pt, vtNPrev) ;
|
|
||||||
Point3d ptPrev ;
|
|
||||||
Point3d ptNext ;
|
|
||||||
// interseco con il piano precedente prendendo i tratti successivi
|
|
||||||
bool bFound = false ;
|
|
||||||
// parto a confrontare i segmenti successivi a quelli identificati come concavi
|
|
||||||
if ( ! bCheckingStart)
|
|
||||||
c = i + 2 ;
|
|
||||||
else // se sono arrivato a fine curva di una curva chiusa controllo con lo start
|
|
||||||
c = 1 ;
|
|
||||||
while ( ! bFound && c > 0) {
|
|
||||||
Point3d ptInt ;
|
|
||||||
Point3d ptStart, ptEnd ;
|
|
||||||
vOffsetCrvs[c].pCrv->GetStartPoint( ptStart) ;
|
|
||||||
vOffsetCrvs[c].pCrv->GetEndPoint( ptEnd) ;
|
|
||||||
IntersLinePlane( ptStart, ptEnd, plPrev, ptInt, false) ;
|
|
||||||
Vector3d vtDir ; vOffsetCrvs[c].pCrv->GetStartDir( vtDir) ;
|
|
||||||
double dLen ; vOffsetCrvs[c].pCrv->GetLength( dLen) ;
|
|
||||||
double dU = ( ptInt - ptStart).Len() / dLen ;
|
|
||||||
if ( vtDir * ( ptInt - ptStart) < 0)
|
|
||||||
dU *= -1 ;
|
|
||||||
if ( dU < 1) {
|
|
||||||
ptNext = ptInt ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++c ;
|
|
||||||
}
|
|
||||||
// salvo la modifica nel vettore edit
|
|
||||||
int nNext = c ;
|
|
||||||
vEditInfo[c].nFlag = EditCrvInfo::EditFlag::EDIT ;
|
|
||||||
vEditInfo[c].ptStart = ptNext ;
|
|
||||||
|
|
||||||
// interseco con il piano successivo prendendo i tratti precedenti
|
|
||||||
bFound = false ;
|
|
||||||
c = i - 1 ;
|
|
||||||
while ( ! bFound && c < ssize( vOffsetCrvs)) {
|
|
||||||
Point3d ptInt ;
|
|
||||||
Point3d ptStart, ptEnd ;
|
|
||||||
vOffsetCrvs[c].pCrv->GetStartPoint( ptStart) ;
|
|
||||||
vOffsetCrvs[c].pCrv->GetEndPoint( ptEnd) ;
|
|
||||||
IntersLinePlane( ptStart, ptEnd, plNext, ptInt, false) ;
|
|
||||||
Vector3d vtDir ; vOffsetCrvs[c].pCrv->GetStartDir( vtDir) ;
|
|
||||||
double dLen ; vOffsetCrvs[c].pCrv->GetLength( dLen) ;
|
|
||||||
double dU = ( ptInt - ptStart).Len() / dLen ;
|
|
||||||
if ( vtDir * ( ptInt - ptStart) < 0)
|
|
||||||
dU *= -1 ;
|
|
||||||
if ( dU > 0) {
|
|
||||||
ptPrev = ptInt ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
--c ;
|
|
||||||
}
|
|
||||||
// salvo la modifica nel vettore edit
|
|
||||||
int nPrev = c ;
|
|
||||||
vEditInfo[c].nFlag = EditCrvInfo::EditFlag::EDIT ;
|
|
||||||
vEditInfo[c].ptEnd = ptPrev ;
|
|
||||||
|
|
||||||
// tengo solo il punto più esterno
|
|
||||||
double dLen1 = Dist( ptPrev, pt) ;
|
|
||||||
double dLen2 = Dist( ptNext, pt) ;
|
|
||||||
if ( dLen1 > dLen2)
|
|
||||||
vEditInfo[nNext].ptStart = ptPrev ;
|
|
||||||
else
|
|
||||||
vEditInfo[nPrev].ptStart = ptNext ;
|
|
||||||
|
|
||||||
// setto come da cancellare tutti i tratti nel mezzo
|
|
||||||
if ( ! bCheckingStart) {
|
|
||||||
c = nPrev + 1 ;
|
|
||||||
while ( c < nNext) {
|
|
||||||
vEditInfo[c].nFlag = EditCrvInfo::EditFlag::DEL ;
|
|
||||||
++c ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = nPrev + 1 ;
|
|
||||||
while ( c < ssize( vEditInfo)) {
|
|
||||||
vEditInfo[c].nFlag = EditCrvInfo::EditFlag::DEL ;
|
|
||||||
++c ;
|
|
||||||
}
|
|
||||||
c = 0 ;
|
|
||||||
while ( c < nNext) {
|
|
||||||
vEditInfo[c].nFlag = EditCrvInfo::EditFlag::DEL ;
|
|
||||||
++c ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! bCheckingStart)
|
|
||||||
i = nNext ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
+26
-67
@@ -761,7 +761,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
|
|||||||
|
|
||||||
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
|
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
|
||||||
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
|
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
|
||||||
if ( dMaxSqDist > dSqTol) {
|
if ( dMaxSqDist > dSqTol) {
|
||||||
// inserisco il punto
|
// inserisco il punto
|
||||||
vInd.push_back( nMaxInd) ;
|
vInd.push_back( nMaxInd) ;
|
||||||
// split
|
// split
|
||||||
@@ -775,7 +775,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd, double dMaxLen)
|
PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd)
|
||||||
{
|
{
|
||||||
// se non ci sono almeno 3 punti, esco subito
|
// se non ci sono almeno 3 punti, esco subito
|
||||||
if ( m_lUPoints.size() < 3)
|
if ( m_lUPoints.size() < 3)
|
||||||
@@ -792,65 +792,34 @@ PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd, double dMaxLen)
|
|||||||
// vettore indici dei punti rimanenti
|
// vettore indici dei punti rimanenti
|
||||||
INTVECTOR vInd ; vInd.reserve( vPtU.size()) ;
|
INTVECTOR vInd ; vInd.reserve( vPtU.size()) ;
|
||||||
|
|
||||||
if ( dMaxLen > INFINITO - 1) {
|
// se aperta
|
||||||
// se aperta
|
if ( ! IsClosed()) {
|
||||||
if ( ! IsClosed()) {
|
// considero tutti i punti della PolyLine
|
||||||
// considero tutti i punti della PolyLine
|
vInd.push_back( 0) ;
|
||||||
vInd.push_back( 0) ;
|
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
|
||||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
|
return false ;
|
||||||
return false ;
|
vInd.push_back( int( vPtU.size()) - 1) ;
|
||||||
vInd.push_back( int( vPtU.size()) - 1) ;
|
|
||||||
}
|
|
||||||
// altrimenti chiusa
|
|
||||||
else {
|
|
||||||
// cerco il punto più distante dal primo
|
|
||||||
double dMaxDist = 0. ;
|
|
||||||
int nMaxInd = 0 ;
|
|
||||||
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
|
|
||||||
double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ;
|
|
||||||
if ( dCurrDist > dMaxDist) {
|
|
||||||
dMaxDist = dCurrDist ;
|
|
||||||
nMaxInd = i ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// recupero due PolyLine di approssimazione
|
|
||||||
vInd.push_back( 0) ;
|
|
||||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd))
|
|
||||||
return false ;
|
|
||||||
vInd.push_back( nMaxInd) ;
|
|
||||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
|
|
||||||
return false ;
|
|
||||||
vInd.push_back( int( vPtU.size()) - 1) ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// altrimenti chiusa
|
||||||
else {
|
else {
|
||||||
// raggruppo i punti della polyline a gruppi che stanno entro la lunghezza massima e ad ognuno applico Douglas
|
// cerco il punto più distante dal primo
|
||||||
vInd.push_back(0) ;
|
double dMaxDist = 0. ;
|
||||||
|
int nMaxInd = 0 ;
|
||||||
int i = 0 ;
|
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
|
||||||
while ( i < ssize(vPtU) - 1) {
|
double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ;
|
||||||
int nLast = i + 1 ;
|
if ( dCurrDist > dMaxDist) {
|
||||||
while ( nLast < ssize( vPtU) && Dist( vPtU[i].first, vPtU[nLast].first) <= dMaxLen)
|
dMaxDist = dCurrDist ;
|
||||||
++nLast ;
|
nMaxInd = i ;
|
||||||
|
|
||||||
// l'ultimo punto era oltre il limite
|
|
||||||
--nLast ;
|
|
||||||
|
|
||||||
// sicurezza: almeno un passo avanti
|
|
||||||
if ( nLast == i)
|
|
||||||
nLast = i + 1 ;
|
|
||||||
|
|
||||||
// mantieni l'estremo del tratto
|
|
||||||
if ( vInd.back() != nLast)
|
|
||||||
vInd.push_back( nLast) ;
|
|
||||||
|
|
||||||
// semplifica il tratto interno
|
|
||||||
if ( nLast - i > 1) {
|
|
||||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, i, nLast, vInd))
|
|
||||||
return false ;
|
|
||||||
}
|
}
|
||||||
i = nLast ;
|
|
||||||
}
|
}
|
||||||
|
// recupero due PolyLine di approssimazione
|
||||||
|
vInd.push_back( 0) ;
|
||||||
|
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd))
|
||||||
|
return false ;
|
||||||
|
vInd.push_back( nMaxInd) ;
|
||||||
|
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
|
||||||
|
return false ;
|
||||||
|
vInd.push_back( int( vPtU.size()) - 1) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ordino in senso crescente
|
// ordino in senso crescente
|
||||||
@@ -1649,9 +1618,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
|||||||
int nPnt2 = PL2.GetPointNbr() ;
|
int nPnt2 = PL2.GetPointNbr() ;
|
||||||
if ( nPnt1 == 0 || nPnt2 == 0)
|
if ( nPnt1 == 0 || nPnt2 == 0)
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
bool bClosed1 = PL1.IsClosed() ;
|
|
||||||
bool bClosed2 = PL2.IsClosed() ;
|
|
||||||
|
|
||||||
// indica la presenza di punti interni in comune tra le due polylines
|
// indica la presenza di punti interni in comune tra le due polylines
|
||||||
bCommonInternalPoints = false ;
|
bCommonInternalPoints = false ;
|
||||||
@@ -1697,10 +1663,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
|||||||
if ( nMinJ < nLastJ)
|
if ( nMinJ < nLastJ)
|
||||||
nMinJ = nLastJ ;
|
nMinJ = nLastJ ;
|
||||||
|
|
||||||
// se la curva è chiusa il primo e l'ultimo punto coincidono, verifico quale conviene considerare
|
|
||||||
if ( bClosed2 && nMinJ == nTotP2 - 1 && nLastJ == 0)
|
|
||||||
nMinJ = 0 ;
|
|
||||||
|
|
||||||
// verifica se è un punto interno in comune con l'altra polyline
|
// verifica se è un punto interno in comune con l'altra polyline
|
||||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||||
bCommonInternalPoints = true ;
|
bCommonInternalPoints = true ;
|
||||||
@@ -1731,9 +1693,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
|||||||
|
|
||||||
if ( nMinI < nLastI)
|
if ( nMinI < nLastI)
|
||||||
nMinI = nLastI ;
|
nMinI = nLastI ;
|
||||||
|
|
||||||
if ( bClosed1 && nMinI == nTotP1 - 1 && nLastI == 0)
|
|
||||||
nMinI = 0 ;
|
|
||||||
|
|
||||||
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||||
bCommonInternalPoints = true ;
|
bCommonInternalPoints = true ;
|
||||||
|
|||||||
+25
-345
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
//--------------------------- Include ----------------------------------------
|
//--------------------------- Include ----------------------------------------
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include <cmath>
|
|
||||||
#include "SurfTriMesh.h"
|
#include "SurfTriMesh.h"
|
||||||
#include "SurfBezier.h"
|
#include "SurfBezier.h"
|
||||||
#include "GeoConst.h"
|
#include "GeoConst.h"
|
||||||
@@ -33,6 +32,14 @@ using namespace std ;
|
|||||||
const double COS_ANG_LIM = 0.0175 ;
|
const double COS_ANG_LIM = 0.0175 ;
|
||||||
// Angolo massimo tra normali per effettuare bisezione su spigolo
|
// Angolo massimo tra normali per effettuare bisezione su spigolo
|
||||||
const double COS_ANG_MAX_CORNER = 0.8660 ;
|
const double COS_ANG_MAX_CORNER = 0.8660 ;
|
||||||
|
// Tipologia di punto
|
||||||
|
const int P5AX_TO_DELETE = -1 ; // da cancellare
|
||||||
|
const int P5AX_OUT = 0 ; // aggiunto prima di inizio o dopo fine
|
||||||
|
const int P5AX_STD = 1 ; // standard
|
||||||
|
const int P5AX_CVEX = 2 ; // su angolo convesso
|
||||||
|
const int P5AX_CONC = 3 ; // in angolo concavo
|
||||||
|
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
|
||||||
|
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
static double
|
static double
|
||||||
@@ -57,7 +64,6 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
|
|||||||
static bool
|
static bool
|
||||||
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||||
{
|
{
|
||||||
const double dSinSmallAngle = sin( 0.5 * DEGTORAD) ;
|
|
||||||
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
|
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
|
||||||
// precedente
|
// precedente
|
||||||
int j = i - 1 ;
|
int j = i - 1 ;
|
||||||
@@ -73,47 +79,18 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
|||||||
Point3d ptInt ;
|
Point3d ptInt ;
|
||||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||||
// verifico se spigolo convesso o concavo
|
// verifico se spigolo convesso o concavo
|
||||||
double dProjPrev = ( vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 ;
|
bool bConvex ;
|
||||||
double dProjCurr = ( vPt5ax[j].ptP - vPt5ax[i].ptP) * vPt5ax[i].vtDir1 ;
|
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||||
bool bConvex = ( abs( dProjCurr) > abs( dProjPrev) ? dProjCurr < 0 : dProjPrev < 0) ;
|
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||||
int nPrev = i - 1 ;
|
else
|
||||||
if ( i < ssize( vPt5ax) - 2 && ! AreSameVectorExact(vPt5ax[i - 1].vtDir1, vPt5ax[i - 1].vtDir2)) {
|
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||||
int z = nPrev - 1 ;
|
|
||||||
// se vtDir1 e vtDir2 sono diverse allora sono su uno spigolo
|
|
||||||
double dProjPrev2 = ( vPt5ax[z].ptP - vPt5ax[nPrev].ptP) * vPt5ax[nPrev].vtDir2 ;
|
|
||||||
double dProjCurr2 = ( vPt5ax[i].ptP - vPt5ax[nPrev].ptP) * vPt5ax[nPrev].vtDir1 ;
|
|
||||||
// se uno dei due è convesso allora considero convesso l'angolo
|
|
||||||
bConvex = dProjPrev2 < EPS_SMALL || dProjCurr2 < EPS_SMALL ;
|
|
||||||
}
|
|
||||||
bool bValidIntersAfterJ = true ;
|
|
||||||
bool bValidIntersBeforeI = true ;
|
|
||||||
if ( i > 2) {
|
|
||||||
// verifico che l'intersezione sia tra i e j e non prima di j
|
|
||||||
int k = i - 2 ;
|
|
||||||
bValidIntersAfterJ = ( ptInt - vPt5ax[j].ptP) * ( vPt5ax[j].ptP - vPt5ax[k].ptP) > 0 ;
|
|
||||||
bool bBetweenIAndJ = ( ptInt - vPt5ax[j].ptP) * ( vPt5ax[i].ptP - vPt5ax[j].ptP) > 0 ;
|
|
||||||
bValidIntersAfterJ = bValidIntersAfterJ && bBetweenIAndJ ;
|
|
||||||
}
|
|
||||||
if ( i < ssize( vPt5ax) - 1) {
|
|
||||||
// verifico anche che l'intersezione non sia dopo i
|
|
||||||
int h = i + 1 ;
|
|
||||||
bValidIntersBeforeI = ( ptInt - vPt5ax[i].ptP) * ( vPt5ax[h].ptP - vPt5ax[i].ptP) < 0 ;
|
|
||||||
bool bBetweenIAndJ = ( ptInt - vPt5ax[i].ptP) * ( vPt5ax[i].ptP - vPt5ax[j].ptP) < 0 ;
|
|
||||||
bValidIntersBeforeI = bValidIntersBeforeI && bBetweenIAndJ ;
|
|
||||||
}
|
|
||||||
bool bValidInters = ( bValidIntersAfterJ && bValidIntersBeforeI) ;
|
|
||||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||||
if ( bConvex) {
|
if ( bConvex) {
|
||||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||||
if ( dLen1 > 10 * EPS_SMALL && bValidIntersAfterJ) {
|
if ( dLen1 > 2 * EPS_SMALL) {
|
||||||
Point5ax Pt5ax ;
|
Point5ax Pt5ax ;
|
||||||
if ( bValidInters)
|
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
|
||||||
else {
|
|
||||||
Vector3d vtNewLine = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtNewLine.Normalize() ;
|
|
||||||
Pt5ax.ptP = vPt5ax[i].ptP - vtNewLine * 2 * EPS_SMALL ;
|
|
||||||
}
|
|
||||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||||
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
|
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
|
||||||
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
|
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
|
||||||
@@ -125,14 +102,9 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
vPt5ax[j].nFlag = P5AX_CVEX ;
|
vPt5ax[j].nFlag = P5AX_CVEX ;
|
||||||
if ( dLen2 > 10 * EPS_SMALL && bValidIntersBeforeI) {
|
if ( dLen2 > 2 * EPS_SMALL) {
|
||||||
Point5ax Pt5ax ;
|
Point5ax Pt5ax ;
|
||||||
if ( bValidInters)
|
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
|
||||||
else {
|
|
||||||
Vector3d vtNewLine = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtNewLine.Normalize() ;
|
|
||||||
Pt5ax.ptP = vPt5ax[j].ptP + vtNewLine * 2 * EPS_SMALL ;
|
|
||||||
}
|
|
||||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||||
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
|
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
|
||||||
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
|
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
|
||||||
@@ -161,72 +133,6 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// guardo se la proiezione il tratto successivo, lungo la normale precedente + maggiore di un angolo minimo ( angolo interno smooth)
|
|
||||||
Vector3d vtDirNext = vPt5ax[i].ptP - vPt5ax[j].ptP ;
|
|
||||||
vtDirNext.Normalize() ;
|
|
||||||
double dProj1 = vtDirNext * vPt5ax[j].vtDir1 ;
|
|
||||||
double dProj2 = ( - vtDirNext) * vPt5ax[i].vtDir1 ;
|
|
||||||
|
|
||||||
if ( ( abs( dProj1) > abs( dProj2) ? dProj1 > dSinSmallAngle : dProj2 > dSinSmallAngle)) {
|
|
||||||
// se concavo senza spigolo netto segnalo zona concava smooth
|
|
||||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0 ;
|
|
||||||
int j = ssize( vPt5ax) - 1 ;
|
|
||||||
bool bClosed = AreSamePointApprox( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
|
|
||||||
// se la curva è chiusa controllo inizio e fine
|
|
||||||
if ( bClosed) {
|
|
||||||
// se normali tra corrente e precedente oltre limite
|
|
||||||
int k = i + 1 ;
|
|
||||||
int z = j - 1 ;
|
|
||||||
double dProjPrev = ( vPt5ax[z].ptP - vPt5ax[j].ptP) * vPt5ax[i].vtDir1 ;
|
|
||||||
double dProjCurr = ( vPt5ax[k].ptP - vPt5ax[i].ptP) * vPt5ax[j].vtDir1 ;
|
|
||||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER) {
|
|
||||||
bool bConvex = ( abs( dProjCurr) > abs( dProjPrev) ? dProjCurr < 0 : dProjPrev < 0) ;
|
|
||||||
if ( i < ssize( vPt5ax) - 2 && ! AreSameVectorExact(vPt5ax.back().vtDir1, vPt5ax.back().vtDir2)) {
|
|
||||||
int z = j - 1 ;
|
|
||||||
// se vtDir1 e vtDir2 sono diverse allora sono su uno spigolo
|
|
||||||
double dProjPrev2 = ( vPt5ax[z].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir2 ;
|
|
||||||
double dProjCurr2 = ( vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 ;
|
|
||||||
// se uno dei due è convesso allora considero convesso l'angolo
|
|
||||||
bConvex = dProjPrev2 < EPS_SMALL || dProjCurr2 < EPS_SMALL ;
|
|
||||||
}
|
|
||||||
if ( bConvex) {
|
|
||||||
vPt5ax[i].nFlag = P5AX_CVEX ;
|
|
||||||
vPt5ax[i].vtDir2 = vPt5ax[j].vtDir1 ;
|
|
||||||
vPt5ax[j].nFlag = P5AX_CVEX ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vPt5ax[i].nFlag = P5AX_CONC ;
|
|
||||||
vPt5ax[j].nFlag = P5AX_CONC ;
|
|
||||||
Vector3d vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; vtDir1.Normalize() ;
|
|
||||||
Vector3d vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; vtDir2.Normalize() ;
|
|
||||||
Vector3d vtDirU = Media( vPt5ax[i].vtDirU, vPt5ax[j].vtDirU) ; vtDirU.Normalize() ;
|
|
||||||
Vector3d vtDirV = Media( vPt5ax[i].vtDirV, vPt5ax[j].vtDirV) ; vtDirV.Normalize() ;
|
|
||||||
vPt5ax[i].vtDir1 = vtDir1 ;
|
|
||||||
vPt5ax[j].vtDir1 = vtDir1 ;
|
|
||||||
vPt5ax[i].vtDir2 = vtDir2 ;
|
|
||||||
vPt5ax[j].vtDir2 = vtDir2 ;
|
|
||||||
vPt5ax[i].vtDirU = vtDirU ;
|
|
||||||
vPt5ax[j].vtDirU = vtDirU ;
|
|
||||||
vPt5ax[i].vtDirV = vtDirV ;
|
|
||||||
vPt5ax[j].vtDirV = vtDirV ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( abs( dProjPrev) > abs( dProjCurr) ? dProjPrev > dSinSmallAngle : dProjCurr > dSinSmallAngle) {
|
|
||||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
|
||||||
vPt5ax[j].nFlag = P5AX_SMOOTH_CONC ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// riscorro tutto il vettore per vedere se ho creato delle zone concave smooth frammentate (separate solo da un tratto non classificato concavo), che quindi uniformo
|
|
||||||
for ( int i = 1 ; i < ssize( vPt5ax) - 1 ; ++ i) {
|
|
||||||
if ( vPt5ax[i].nFlag != P5AX_SMOOTH_CONC && vPt5ax[i-1].nFlag == P5AX_SMOOTH_CONC && vPt5ax[i+1].nFlag == P5AX_SMOOTH_CONC)
|
|
||||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
|
||||||
}
|
}
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
@@ -438,7 +344,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
||||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax, bool bNormOrTang)
|
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||||
{
|
{
|
||||||
// controllo le tolleranze
|
// controllo le tolleranze
|
||||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||||
@@ -458,118 +364,21 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
|||||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||||
|
|
||||||
// proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza
|
// proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza
|
||||||
double dPar, dParNext ;
|
double dPar ;
|
||||||
Point3d ptP, ptPNext ;
|
Point3d ptP ;
|
||||||
Vector3d vtDirPrev = V_INVALID ;
|
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||||
if ( PL.IsClosed()) {
|
|
||||||
Point3d pt1, pt2 ;
|
|
||||||
PL.GetLastLine( pt1, pt2) ;
|
|
||||||
vtDirPrev = pt2 - pt1 ;
|
|
||||||
}
|
|
||||||
Vector3d vtLast ; PL.GetLastULine( &dPar, &ptP, &dParNext, &ptPNext) ;
|
|
||||||
vtLast = ptPNext - ptP ; vtLast.Normalize() ;
|
|
||||||
bool bFound = PL.GetFirstULine( &dPar, &ptP, &dParNext, &ptPNext) ;
|
|
||||||
Vector3d vtFirst = ptPNext - ptP ; vtFirst.Normalize() ;
|
|
||||||
bool bClosed = PL.IsClosed() ;
|
|
||||||
bool bLast = false ;
|
|
||||||
Vector3d vtNormPrev = V_INVALID ;
|
|
||||||
Point3d ptPrev ;
|
|
||||||
bool bFirst = true ;
|
|
||||||
while ( bFound) {
|
while ( bFound) {
|
||||||
// se trovo proiezione, la salvo
|
// se trovo proiezione, la salvo
|
||||||
Point5ax Pt5ax ;
|
Point5ax Pt5ax ;
|
||||||
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
|
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
|
||||||
vPt5ax.emplace_back( Pt5ax) ;
|
vPt5ax.emplace_back( Pt5ax) ;
|
||||||
// controllo che la normale trovata sia in linea con la precedente, se i due tratti erano abbastanza allineati
|
// passo al successivo
|
||||||
bool bRecalc = false ;
|
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||||
if ( bFirst)
|
|
||||||
bRecalc = true ;
|
|
||||||
if ( ssize( vPt5ax) > 2) {
|
|
||||||
Point5ax& pt5Curr = vPt5ax.back() ;
|
|
||||||
Point5ax& pt5Prev = vPt5ax.end()[-2] ;
|
|
||||||
Point5ax& pt5PrevPrev = vPt5ax.end()[-3] ;
|
|
||||||
Vector3d vtDirCurr = pt5Curr.ptP - pt5Prev.ptP ; vtDirCurr.Normalize() ;
|
|
||||||
Vector3d vtDirPrev = pt5Prev.ptP - pt5PrevPrev.ptP ; vtDirPrev.Normalize() ;
|
|
||||||
double dProjDir = vtDirCurr * vtDirPrev ;
|
|
||||||
if ( dProjDir > COS_ANG_MAX_CORNER) {
|
|
||||||
double dProjNorm = vPt5ax.back().vtDir1 * vtNormPrev ;
|
|
||||||
if ( dProjNorm < COS_ANG_MAX_CORNER)
|
|
||||||
bRecalc = true ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vector3d vtDirNext = ptPNext - ptP ; vtDirNext.Normalize() ;
|
|
||||||
// se sono arrivato ad uno spigolo tengo la normale appena prima dello spigolo
|
|
||||||
if ( bRecalc) {
|
|
||||||
Point3d ptAlter ;
|
|
||||||
if ( ! bFirst) {
|
|
||||||
Vector3d vtDirPrev = ptP - ptPrev ; vtDirPrev.Normalize() ;
|
|
||||||
ptAlter = ptP - vtDirPrev * 5 * EPS_SMALL ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ptAlter = ptP + vtDirNext * 5 * EPS_SMALL ;
|
|
||||||
Point5ax Pt5axRec ;
|
|
||||||
if ( ProjectPointOnSurf( ptAlter, vpSurf, dPar, Pt5axRec)) {
|
|
||||||
// aggiorno solo la vtDir1, la vtDir2 la mantengo con la normale successiva allo spigolo
|
|
||||||
if ( Pt5axRec.vtDir1 * Pt5ax.vtDir1 < COS_ANG_MAX_CORNER)
|
|
||||||
vPt5ax.back().vtDir1 = Pt5axRec.vtDir1 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( ssize( vPt5ax) > 1 && vPt5ax.back().vtDir1 * vPt5ax.end()[-2].vtDir1 < COS_ANG_MAX_CORNER) {
|
|
||||||
// se la normale corrente è sufficientemente diversa dalla precedente e i tratti non erano allineati
|
|
||||||
// controllo se il punto precedente erano su uno spigolo, ricalcolando in un punto appena oltre
|
|
||||||
Point3d ptAlter = ptPrev + ( ptP - ptPrev) * 5 * EPS_SMALL ;
|
|
||||||
Point5ax Pt5axRec ;
|
|
||||||
if ( ProjectPointOnSurf( ptAlter, vpSurf, dPar, Pt5axRec)) {
|
|
||||||
// aggiorno solo la vtDir1, la vtDir2 la mantengo con la normale successiva allo spigolo
|
|
||||||
if ( Pt5axRec.vtDir1 * Pt5ax.vtDir1 < COS_ANG_MAX_CORNER)
|
|
||||||
vPt5ax.end()[-2].vtDir1 = Pt5axRec.vtDir1 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bLast && bClosed) {
|
|
||||||
// controllo se il punto finale è di spigolo
|
|
||||||
if ( vPt5ax.back().vtDir1 * vPt5ax.front().vtDir1 < COS_ANG_MAX_CORNER) {
|
|
||||||
vPt5ax.back().vtDir2 = vPt5ax.front().vtDir1 ;
|
|
||||||
vPt5ax.front().vtDir2 = vPt5ax.back().vtDir1 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vtNormPrev = vPt5ax.back().vtDir1 ;
|
|
||||||
// se richiesta la tangente anziché la normale allora modifico il vettore associato al punto
|
|
||||||
Vector3d vtDir ;
|
|
||||||
if ( ! bNormOrTang) {
|
|
||||||
Vector3d vtNorm = vPt5ax.back().vtDir1 ;
|
|
||||||
if ( bFirst)
|
|
||||||
vtDir = vtDirNext ;
|
|
||||||
else
|
|
||||||
vtDir = vtDirPrev ;
|
|
||||||
// in caso sia stato superato l'angolo limite dò priorità alla direzione precedente
|
|
||||||
if ( vtDirPrev.IsValid() && (! bFirst || ( bFirst && bClosed))) {
|
|
||||||
double dProj = vtDir * vtDirPrev ;
|
|
||||||
if ( dProj > COS_ANG_MAX_CORNER)
|
|
||||||
vtDir = Media( vtDir, vtDirPrev) ;
|
|
||||||
}
|
|
||||||
vtDirPrev = vtDirNext ;
|
|
||||||
Vector3d vtTang = vtDir ^ vtNorm ; vtTang.Normalize() ;
|
|
||||||
vPt5ax.back().vtDir1 = vtTang ;
|
|
||||||
vPt5ax.back().vtDir2 = vtTang ;
|
|
||||||
}
|
|
||||||
// passo al successivo
|
|
||||||
ptPrev = ptP ;
|
|
||||||
bFound = PL.GetNextULine( &dPar, &ptP, &dParNext, &ptPNext) ;
|
|
||||||
// se sono arrivato alla fine aggiungo l'ultimo punto
|
|
||||||
if ( ! bFound && ! bLast) {
|
|
||||||
bLast = true ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
if ( bFirst)
|
|
||||||
bFirst = false ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||||
if ( bSharpEdges) {
|
if ( bSharpEdges)
|
||||||
if ( ! AddPointsOnCorners( vPt5ax))
|
AddPointsOnCorners( vPt5ax) ;
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rimozione punti in eccesso rispetto alle tolleranze
|
// rimozione punti in eccesso rispetto alle tolleranze
|
||||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||||
@@ -1292,132 +1101,3 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
|||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
GetCurveOnSurfInfo( const ICurve& crCrv, const ISurfTriMesh& pSurf,
|
|
||||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax, bool bNormOrTang)
|
|
||||||
{
|
|
||||||
// controllo le tolleranze
|
|
||||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
|
||||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
|
||||||
|
|
||||||
// approssimo la curva con una polilinea entro la tolleranza
|
|
||||||
PolyLine PL ;
|
|
||||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
|
||||||
if ( ! crCrv.ApproxWithLimitedLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, MAX_SEG_LEN, PL))
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
PL.RemoveAlignedPoints( dLinTol, false, MAX_SEG_LEN) ;
|
|
||||||
|
|
||||||
// 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, dParNext ;
|
|
||||||
Point3d ptP, ptPNext ;
|
|
||||||
Vector3d vtDirPrev = V_INVALID ;
|
|
||||||
if ( PL.IsClosed()) {
|
|
||||||
Point3d pt1, pt2 ;
|
|
||||||
PL.GetLastLine( pt1, pt2) ;
|
|
||||||
vtDirPrev = pt2 - pt1 ;
|
|
||||||
}
|
|
||||||
Vector3d vtLast ; PL.GetLastULine( &dPar, &ptP, &dParNext, &ptPNext) ;
|
|
||||||
vtLast = ptPNext - ptP ; vtLast.Normalize() ;
|
|
||||||
bool bFound = PL.GetFirstULine( &dPar, &ptP, &dParNext, &ptPNext) ;
|
|
||||||
Vector3d vtFirst = ptPNext - ptP ; vtFirst.Normalize() ;
|
|
||||||
bool bClosed = PL.IsClosed() ;
|
|
||||||
bool bLast = false ;
|
|
||||||
Point3d ptPrev ;
|
|
||||||
bool bFirst = true ;
|
|
||||||
const ICurveComposite* pCC = GetCurveComposite( &crCrv) ;
|
|
||||||
int nTria = -1 ;
|
|
||||||
Triangle3dEx trTria ;
|
|
||||||
while ( bFound) {
|
|
||||||
// se trovo proiezione, la salvo
|
|
||||||
Point5ax Pt5ax ;
|
|
||||||
Pt5ax.ptP = ptP ;
|
|
||||||
Pt5ax.dPar = dPar ;
|
|
||||||
double dDecimal ;
|
|
||||||
bool bJoint = modf( dPar, &dDecimal) == 0.0 ;
|
|
||||||
int nCrv = int( bJoint ? dPar - 1 : dPar) ;
|
|
||||||
if ( nCrv < 0)
|
|
||||||
nCrv = 0 ;
|
|
||||||
int nTriaCurr ; pCC->GetCurveTempProp( nCrv, nTriaCurr, 0) ;
|
|
||||||
if ( nTriaCurr != nTria)
|
|
||||||
pSurf.GetTriangle( nTriaCurr, trTria) ;
|
|
||||||
|
|
||||||
if ( ! CalcNormal( ptP, trTria, Pt5ax.vtDir1))
|
|
||||||
Pt5ax.vtDir1 = trTria.GetN() ;
|
|
||||||
nTria = nTriaCurr ;
|
|
||||||
if ( bJoint) {
|
|
||||||
int nPar = int( dPar) ;
|
|
||||||
if ( bClosed && nPar > pCC->GetCurveCount() - 1)
|
|
||||||
nPar = 0 ;
|
|
||||||
int nTria2 ; pCC->GetCurveTempProp( nPar, nTria2, 0) ;
|
|
||||||
Triangle3dEx trTria2 ; pSurf.GetTriangle( nTria2, trTria2) ;
|
|
||||||
if ( ! CalcNormal( ptP, trTria2, Pt5ax.vtDir2))
|
|
||||||
Pt5ax.vtDir2 = trTria2.GetN() ;
|
|
||||||
nTria = nTria2 ;
|
|
||||||
trTria = trTria2 ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Pt5ax.vtDir2 = Pt5ax.vtDir1 ;
|
|
||||||
Pt5ax.vtDirU = V_NULL ;
|
|
||||||
Pt5ax.vtDirV = V_NULL ;
|
|
||||||
Pt5ax.nFlag = P5AX_STD ;
|
|
||||||
vPt5ax.emplace_back( Pt5ax) ;
|
|
||||||
|
|
||||||
Vector3d vtDirNext = ptPNext - ptP ; vtDirNext.Normalize() ;
|
|
||||||
// se richiesta la tangente anziché la normale allora modifico il vettore associato al punto
|
|
||||||
Vector3d vtDir ;
|
|
||||||
if ( ! bNormOrTang) {
|
|
||||||
Vector3d vtNorm = vPt5ax.back().vtDir1 ;
|
|
||||||
if ( bFirst)
|
|
||||||
vtDir = vtDirNext ;
|
|
||||||
else
|
|
||||||
vtDir = vtDirPrev ;
|
|
||||||
// in caso sia stato superato l'angolo limite dò priorità alla direzione precedente
|
|
||||||
bool bEdge = false ;
|
|
||||||
if ( vtDirPrev.IsValid() && (! bFirst || ( bFirst && bClosed))) {
|
|
||||||
double dProj = vtDirNext * vtDirPrev ;
|
|
||||||
bEdge = dProj < COS_ANG_MAX_CORNER ;
|
|
||||||
if ( ! bEdge)
|
|
||||||
vtDir = Media( vtDirNext, vtDirPrev) ;
|
|
||||||
}
|
|
||||||
vtDirPrev = vtDirNext ;
|
|
||||||
bEdge = bEdge || ! AreSameVectorExact( vPt5ax.back().vtDir1, vPt5ax.back().vtDir2) ;
|
|
||||||
Vector3d vtTang = vtDir ^ vtNorm ; vtTang.Normalize() ;
|
|
||||||
vPt5ax.back().vtDir1 = vtTang ;
|
|
||||||
if ( bEdge) {
|
|
||||||
Vector3d vtTang2 = vtDirNext ^ vPt5ax.back().vtDir2 ;
|
|
||||||
vtTang2.Normalize() ;
|
|
||||||
vPt5ax.back().vtDir2 = vtTang2 ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vPt5ax.back().vtDir2 = vtTang ;
|
|
||||||
}
|
|
||||||
// passo al successivo
|
|
||||||
ptPrev = ptP ;
|
|
||||||
bFound = PL.GetNextULine( &dPar, &ptP, &dParNext, &ptPNext) ;
|
|
||||||
// se sono arrivato alla fine aggiungo l'ultimo punto
|
|
||||||
if ( ! bFound && ! bLast) {
|
|
||||||
bLast = true ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
if ( bFirst)
|
|
||||||
bFirst = false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
|
||||||
if ( bSharpEdges) {
|
|
||||||
if ( ! AddPointsOnCorners( vPt5ax))
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rimozione punti in eccesso rispetto alle tolleranze
|
|
||||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|||||||
+551
-1416
File diff suppressed because it is too large
Load Diff
+154
-77
@@ -5976,6 +5976,103 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Calcolo della curva di Sync tra un punto di una curva di Bordo (calcolato come il punto a curvatura massima) e il suo
|
||||||
|
// associato sull'altra Curva di Bordo
|
||||||
|
// -> Restituisce la singola Linea di Sincronizzazione
|
||||||
|
static bool
|
||||||
|
CalcSyncPointFromCurvature( const CurvaturePoint& PointK, const ICurveComposite* pCompoSubEdge, BIPOINT& SyncLine)
|
||||||
|
{
|
||||||
|
// Verifico la validità del SubEdge su cui trovare il punto di Sincronizzazione
|
||||||
|
if ( pCompoSubEdge == nullptr || ! pCompoSubEdge->IsValid())
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
// --- Piano di taglio per punto a distanza minima
|
||||||
|
double dUCurrSubEdge = 0. ;
|
||||||
|
IntersCurvePlane ICP( *pCompoSubEdge, PointK.ptCurvature, Media( PointK.vtTanPrev, PointK.vtTanNext)) ;
|
||||||
|
int nIndParCloser = -1, nIndPointCloser = -1 ;
|
||||||
|
double dSqMinDist = INFINITO ;
|
||||||
|
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||||
|
IntCrvPlnInfo aInfo ;
|
||||||
|
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo)) {
|
||||||
|
if ( nIndParCloser == -1)
|
||||||
|
nIndParCloser = nInfo ;
|
||||||
|
double dSqDist = SqDist( PointK.ptCurvature, aInfo.Ici[0].ptI) ;
|
||||||
|
if ( dSqDist < dSqMinDist) {
|
||||||
|
dSqMinDist = dSqDist ;
|
||||||
|
nIndPointCloser = nInfo ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||||
|
if ( bOkPlane) {
|
||||||
|
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||||
|
if ( nIndParCloser == nIndPointCloser) {
|
||||||
|
IntCrvPlnInfo aInfo ;
|
||||||
|
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||||
|
dUCurrSubEdge = aInfo.Ici[0].dU ;
|
||||||
|
}
|
||||||
|
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||||
|
else {
|
||||||
|
// scelgo il punto più vicino al corrente
|
||||||
|
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||||
|
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||||
|
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||||
|
dUCurrSubEdge = ( SqDist( PointK.ptCurvature, aInfoPt.Ici[0].ptI) < SqDist( PointK.ptCurvature, aInfoPar.Ici[0].ptI) ?
|
||||||
|
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! bOkPlane) {
|
||||||
|
// --- Altrimenti, cerco il punto a minima distanza
|
||||||
|
DistPointCurve DPC( PointK.ptCurvature, *pCompoSubEdge) ;
|
||||||
|
int nFlag ;
|
||||||
|
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( 0., dUCurrSubEdge, nFlag)) ;
|
||||||
|
if ( ! bOkMinDist) {
|
||||||
|
// --- Alla peggio mi posiziono a metà tra la posizione corrente e quella finale
|
||||||
|
double dPrevLen ; pCompoSubEdge->GetLengthAtParam( 0., dPrevLen) ;
|
||||||
|
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||||
|
pCompoSubEdge->GetParamAtLength( ( dPrevLen + dLen) / 2., dUCurrSubEdge) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Definisco il primo estremo della linea di Sincronizzazione corrente
|
||||||
|
SyncLine.first = PointK.ptCurvature ;
|
||||||
|
|
||||||
|
// Verifico se posso muovermi attorno al punto trovato per allinearmi meglio con le normali alla curva
|
||||||
|
// NB. Si cerca di privilgiare i punti più vicini ( in parametro) al punto calcolato sopra, in modo da cercare di
|
||||||
|
// non discostare troppo la Linea di sincronizzazione dal punto trovato.
|
||||||
|
const double MAX_DIST = 2.5 ;
|
||||||
|
const int NUM_SAMPLE_PNT = 20 ;
|
||||||
|
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||||
|
double dSyncLen ; pCompoSubEdge->GetLengthAtParam( dUCurrSubEdge, dSyncLen) ;
|
||||||
|
Vector3d vtSyncTanPrev, vtSyncTanNext ;
|
||||||
|
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_MINUS, SyncLine.second, &vtSyncTanPrev) ; vtSyncTanPrev.Normalize() ;
|
||||||
|
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_PLUS, SyncLine.second, &vtSyncTanNext) ; vtSyncTanNext.Normalize() ;
|
||||||
|
double dLimInfLen = Clamp( dSyncLen - MAX_DIST, 0., dLen) ;
|
||||||
|
double dLimSupLen = Clamp( dSyncLen + MAX_DIST, 0., dLen) ;
|
||||||
|
int nSamplePnt = int( ceil( NUM_SAMPLE_PNT / 4.)) ;
|
||||||
|
double dMaxCos = ( Media( PointK.vtTanPrev, PointK.vtTanNext) * Media( vtSyncTanPrev, vtSyncTanNext)) ;
|
||||||
|
double dShiftR = ( dLimSupLen - dSyncLen) / nSamplePnt ;
|
||||||
|
double dShiftL = ( dSyncLen - dLimInfLen) / nSamplePnt ;
|
||||||
|
array<double, 2> vdLens = { dSyncLen, dSyncLen} ;
|
||||||
|
for ( int i = 1 ; i <= nSamplePnt ; ++ i) {
|
||||||
|
vdLens[0] += dShiftR ;
|
||||||
|
vdLens[1] -= dShiftL ;
|
||||||
|
for ( int j = 0 ; j < 2 ; ++ j) {
|
||||||
|
double dU ; pCompoSubEdge->GetParamAtLength( vdLens[j], dU) ;
|
||||||
|
Point3d ptCurr ; Vector3d vtTan ;
|
||||||
|
pCompoSubEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr, &vtTan) ; vtTan.Normalize() ;
|
||||||
|
double dCos = ( vtTan * Media( PointK.vtTanPrev, PointK.vtTanNext)) ;
|
||||||
|
if ( dCos > dMaxCos) {
|
||||||
|
dMaxCos = dCos ;
|
||||||
|
SyncLine.second = ptCurr ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Gestione degli spigoli all'interno della Quadrangolazione corrente
|
// Gestione degli spigoli all'interno della Quadrangolazione corrente
|
||||||
static bool
|
static bool
|
||||||
@@ -6087,7 +6184,7 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Calcolo delle Curve di Sync per evitare Twist
|
// Calcolo delle Curve di Sync per evitare Twist
|
||||||
static bool
|
static bool
|
||||||
ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines, bool& bEraseLastIso)
|
ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines)
|
||||||
{
|
{
|
||||||
// Verifica validità delle curve
|
// Verifica validità delle curve
|
||||||
if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid())
|
if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid())
|
||||||
@@ -6095,29 +6192,24 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
|||||||
|
|
||||||
const double COS_LIMIT = cos( 50. * DEGTORAD) ;
|
const double COS_LIMIT = cos( 50. * DEGTORAD) ;
|
||||||
const int NUM_SAMPLE_PNT = 20 ;
|
const int NUM_SAMPLE_PNT = 20 ;
|
||||||
const int nStepSkip = NUM_SAMPLE_PNT / 10 ;
|
|
||||||
#if DEBUG_CURVATURE
|
#if DEBUG_CURVATURE
|
||||||
vector<pair<Point3d, double>> _vPtK1 ;
|
vector<pair<Point3d, double>> _vPtK1 ;
|
||||||
vector<pair<Point3d, double>> _vPtK2 ;
|
vector<pair<Point3d, double>> _vPtK2 ;
|
||||||
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
||||||
VERIFY_GEOMDB( pGeomDB, false)
|
VERIFY_GEOMDB( pGeomDB, false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int nLastSync = ssize( vSyncLines) ;
|
|
||||||
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine della prima curva di Bordo
|
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine della prima curva di Bordo
|
||||||
Vector3d vtS1 ; pSubEdge1->GetStartDir( vtS1) ;
|
Vector3d vtS1 ; pSubEdge1->GetStartDir( vtS1) ;
|
||||||
Vector3d vtE1 ; pSubEdge1->GetEndDir( vtE1) ;
|
Vector3d vtE1 ; pSubEdge1->GetEndDir( vtE1) ;
|
||||||
double dLen1 = - EPS_SMALL ;
|
double dLen1 = - EPS_SMALL ;
|
||||||
double dLen2 = - EPS_SMALL ;
|
|
||||||
pSubEdge1->GetLength( dLen1) ;
|
|
||||||
pSubEdge2->GetLength( dLen2) ;
|
|
||||||
double dMyDist = min( dLen1, dLen2) * 0.85 ;
|
|
||||||
bool bSplit1 = ( vtS1 * vtE1 < COS_LIMIT) ;
|
bool bSplit1 = ( vtS1 * vtE1 < COS_LIMIT) ;
|
||||||
if ( bSplit1) {
|
if ( bSplit1) {
|
||||||
// Individuo il punto a Curvatura Massima
|
// Individuo il punto a Curvatura Massima
|
||||||
|
pSubEdge1->GetLength( dLen1) ;
|
||||||
double dKMax1 = - INFINITO + 1, dUK1Max = - EPS_SMALL ;
|
double dKMax1 = - INFINITO + 1, dUK1Max = - EPS_SMALL ;
|
||||||
Point3d ptKMax1 ; Vector3d vtTanKMax1Prev, vtTanKMax1Next ;
|
Point3d ptKMax1 ; Vector3d vtTanKMax1Prev, vtTanKMax1Next ;
|
||||||
for ( int i = nStepSkip ; i <= NUM_SAMPLE_PNT - nStepSkip ; ++ i) {
|
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||||
// Ricavo la Lunghezza corrente e il parametro dU associato
|
// Ricavo la Lunghezza corrente e il parametro dU associato
|
||||||
double dCurrLen1 = Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1) ;
|
double dCurrLen1 = Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1) ;
|
||||||
double dUCurr1 ; pSubEdge1->GetParamAtLength( dCurrLen1, dUCurr1) ;
|
double dUCurr1 ; pSubEdge1->GetParamAtLength( dCurrLen1, dUCurr1) ;
|
||||||
@@ -6145,21 +6237,22 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
|||||||
vtTanKMax1Next.Normalize() ;
|
vtTanKMax1Next.Normalize() ;
|
||||||
// Calcolo la nuova linea di sincronizzazione
|
// Calcolo la nuova linea di sincronizzazione
|
||||||
CurvaturePoint myCurvaturePoint( dUK1Max, ptKMax1, vtTanKMax1Prev, vtTanKMax1Next) ;
|
CurvaturePoint myCurvaturePoint( dUK1Max, ptKMax1, vtTanKMax1Prev, vtTanKMax1Next) ;
|
||||||
double dUOn2 ; double dLenCurr2 ;
|
BIPOINT SyncLine ;
|
||||||
GetIsoPointOnSecondCurve( pSubEdge1, pSubEdge2, dUK1Max, dUOn2, dMyDist, 0, 0, dLenCurr2, dLen2) ;
|
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge2, SyncLine) ;
|
||||||
Point3d ptOn2 ; pSubEdge2->GetPointD1D2( dUOn2, ICurve::FROM_MINUS, ptOn2) ;
|
vSyncLines.emplace_back( SyncLine) ;
|
||||||
vSyncLines.emplace_back( ptKMax1, ptOn2) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto per la prima curva di Bordo
|
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto per la prima curva di Bordo
|
||||||
Vector3d vtS2 ; pSubEdge2->GetStartDir( vtS2) ;
|
Vector3d vtS2 ; pSubEdge2->GetStartDir( vtS2) ;
|
||||||
Vector3d vtE2 ; pSubEdge2->GetEndDir( vtE2) ;
|
Vector3d vtE2 ; pSubEdge2->GetEndDir( vtE2) ;
|
||||||
|
double dLen2 = - EPS_SMALL ;
|
||||||
bool bSplit2 = ( vtS2 * vtE2 < COS_LIMIT) ;
|
bool bSplit2 = ( vtS2 * vtE2 < COS_LIMIT) ;
|
||||||
if ( bSplit2) {
|
if ( bSplit2) {
|
||||||
// Individuo il punto a Curvatura Massima
|
// Individuo il punto a Curvatura Massima
|
||||||
|
pSubEdge2->GetLength( dLen2) ;
|
||||||
double dKMax2 = - INFINITO + 1, dUK2Max = - EPS_SMALL ;
|
double dKMax2 = - INFINITO + 1, dUK2Max = - EPS_SMALL ;
|
||||||
Point3d ptKMax2 ; Vector3d vtTanKMax2Prev, vtTanKMax2Next ;
|
Point3d ptKMax2 ; Vector3d vtTanKMax2Prev, vtTanKMax2Next ;
|
||||||
for ( int i = nStepSkip ; i <= NUM_SAMPLE_PNT - nStepSkip ; ++ i) {
|
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||||
// Ricavo la Lunghezza corrente e il parametro dU associato
|
// Ricavo la Lunghezza corrente e il parametro dU associato
|
||||||
double dCurrLen2 = Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2) ;
|
double dCurrLen2 = Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2) ;
|
||||||
double dUCurr2 ; pSubEdge2->GetParamAtLength( dCurrLen2, dUCurr2) ;
|
double dUCurr2 ; pSubEdge2->GetParamAtLength( dCurrLen2, dUCurr2) ;
|
||||||
@@ -6187,10 +6280,11 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
|||||||
vtTanKMax2Next.Normalize() ;
|
vtTanKMax2Next.Normalize() ;
|
||||||
// Calcolo la nuova linea di sincronizzazione
|
// Calcolo la nuova linea di sincronizzazione
|
||||||
CurvaturePoint myCurvaturePoint( dUK2Max, ptKMax2, vtTanKMax2Prev, vtTanKMax2Next) ;
|
CurvaturePoint myCurvaturePoint( dUK2Max, ptKMax2, vtTanKMax2Prev, vtTanKMax2Next) ;
|
||||||
double dUOn1 ; double dLenCurr1 ;
|
BIPOINT SyncLine ;
|
||||||
GetIsoPointOnSecondCurve( pSubEdge2, pSubEdge1, dUK2Max, dUOn1, dMyDist, 0, 0, dLenCurr1, dLen1) ;
|
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge1, SyncLine) ;
|
||||||
Point3d ptOn1 ; pSubEdge1->GetPointD1D2( dUOn1, ICurve::FROM_MINUS, ptOn1) ;
|
// !<-- Inverto la curva di Sincronizzaione per coerenza con la prima -->!
|
||||||
vSyncLines.emplace_back( ptOn1, ptKMax2) ;
|
swap( SyncLine.first, SyncLine.second) ;
|
||||||
|
vSyncLines.emplace_back( SyncLine) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_CURVATURE // Curvatura minima -> AQUA | Curvatura massima -> ORANGE
|
#if DEBUG_CURVATURE // Curvatura minima -> AQUA | Curvatura massima -> ORANGE
|
||||||
@@ -6235,7 +6329,7 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Se non ho alcuna linea di sincronizzazione, non faccio nulla
|
// Se non ho alcuna linea di sincronizzazione, non faccio nulla
|
||||||
if ( vSyncLines.empty() || ( ! bSplit2 && ! bSplit1))
|
if ( vSyncLines.empty())
|
||||||
return true ;
|
return true ;
|
||||||
|
|
||||||
const double TOL = 250. * EPS_SMALL ;
|
const double TOL = 250. * EPS_SMALL ;
|
||||||
@@ -6244,54 +6338,42 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
|||||||
// NB. Risultano ridondanti, creano SottoQuadrangolazioni molto strette o possono Inclinare eccssivamente l'Utensile
|
// NB. Risultano ridondanti, creano SottoQuadrangolazioni molto strette o possono Inclinare eccssivamente l'Utensile
|
||||||
// NB. Così facendo evito anche di creare curve di Sync lungo le diagonali della Quadrangolazione
|
// NB. Così facendo evito anche di creare curve di Sync lungo le diagonali della Quadrangolazione
|
||||||
const double LEN_TOL = 2. ;
|
const double LEN_TOL = 2. ;
|
||||||
const double dParTol = 0.1 ;
|
for ( int i = 0 ; i < ssize( vSyncLines) ; ++ i) {
|
||||||
double dLenPrev1 = - LEN_TOL, dLenPrev2 = - LEN_TOL ;
|
|
||||||
for ( int i = nLastSync ; i < ssize( vSyncLines) ; ++ i) {
|
|
||||||
double dSyncLen1 ; pSubEdge1->GetLengthAtPoint( vSyncLines[i].first, dSyncLen1, TOL) ;
|
double dSyncLen1 ; pSubEdge1->GetLengthAtPoint( vSyncLines[i].first, dSyncLen1, TOL) ;
|
||||||
bool bErase = ( dSyncLen1 < max( LEN_TOL, dParTol * dLen1) || dSyncLen1 - dLenPrev1 < LEN_TOL) ;
|
bool bErase = ( dSyncLen1 < max( LEN_TOL, 0.2 * dLen1) || dSyncLen1 > min( dLen1 - LEN_TOL, 0.8 * dLen1)) ;
|
||||||
bEraseLastIso = dSyncLen1 > min( dLen1 - LEN_TOL, ( 1 - dParTol) * dLen1) ;
|
|
||||||
if ( ! bErase) {
|
if ( ! bErase) {
|
||||||
double dSyncLen2 ; pSubEdge2->GetLengthAtPoint( vSyncLines[i].second, dSyncLen2, TOL) ;
|
double dSyncLen2 ; pSubEdge2->GetLengthAtPoint( vSyncLines[i].second, dSyncLen2, TOL) ;
|
||||||
bErase = ( dSyncLen2 < max( LEN_TOL, dParTol * dLen2) || dSyncLen2 - dLenPrev2 < LEN_TOL) ;
|
bErase = ( dSyncLen2 < max( LEN_TOL, 0.2 * dLen2) || dSyncLen2 > min( dLen2 - LEN_TOL, 0.8 * dLen2)) ;
|
||||||
bEraseLastIso = bEraseLastIso || dSyncLen2 > min( dLen2 - LEN_TOL, ( 1 - dParTol) * dLen2) ;
|
|
||||||
dLenPrev2 = dSyncLen2 ;
|
|
||||||
}
|
}
|
||||||
if ( bErase && ! bEraseLastIso) {
|
if ( bErase) {
|
||||||
vSyncLines.erase( vSyncLines.begin() + i) ;
|
vSyncLines.erase( vSyncLines.begin() + i) ;
|
||||||
-- i ;
|
-- i ;
|
||||||
}
|
}
|
||||||
dLenPrev1 = dSyncLen1 ;
|
|
||||||
if ( bEraseLastIso)
|
|
||||||
break ;
|
|
||||||
}
|
}
|
||||||
if ( vSyncLines.empty())
|
if ( vSyncLines.empty())
|
||||||
return true ;
|
return true ;
|
||||||
|
|
||||||
// Se due curve di Sincronizzazione rimaste
|
// Se due curve di Sincronizzazione rimaste
|
||||||
if ( ssize( vSyncLines) - nLastSync == 2) {
|
if ( ssize( vSyncLines) == 2) {
|
||||||
// Se si sovrappongono, ne elimino una
|
// Se si sovrappongono, ne elimino una
|
||||||
if ( AreSamePointEpsilon( vSyncLines.end()[-2].first, vSyncLines.end()[-1].first, LEN_TOL) &&
|
if ( AreSamePointEpsilon( vSyncLines[0].first, vSyncLines[1].first, LEN_TOL) &&
|
||||||
AreSamePointEpsilon( vSyncLines.end()[-2].second, vSyncLines.end()[-1].second, LEN_TOL))
|
AreSamePointEpsilon( vSyncLines[0].second, vSyncLines[1].second, LEN_TOL))
|
||||||
vSyncLines.pop_back() ;
|
vSyncLines.pop_back() ;
|
||||||
}
|
}
|
||||||
// Se due curve di Sincronizzazione rimaste
|
// Se due curve di Sincronizzazione rimaste
|
||||||
if ( ssize( vSyncLines) - nLastSync == 2) {
|
if ( ssize( vSyncLines) == 2) {
|
||||||
// Ordino tutte le linee di sincronizzazione in base al parametro dU della curva principale
|
// Ordino tutte le linee di sincronizzazione in base al parametro dU della curva principale
|
||||||
double dU0 ; pSubEdge1->GetParamAtPoint( vSyncLines.end()[-2].first, dU0, TOL) ;
|
double dU0 ; pSubEdge1->GetParamAtPoint( vSyncLines[0].first, dU0, TOL) ;
|
||||||
double dU1 ; pSubEdge1->GetParamAtPoint( vSyncLines.end()[-1].first, dU1, TOL) ;
|
double dU1 ; pSubEdge1->GetParamAtPoint( vSyncLines[1].first, dU1, TOL) ;
|
||||||
if ( dU0 > dU1 - EPS_SMALL)
|
if ( dU0 > dU1 - EPS_SMALL)
|
||||||
swap( vSyncLines.end()[-2], vSyncLines.end()[-1]) ;
|
swap( vSyncLines[0], vSyncLines[1]) ;
|
||||||
// Verifico che le curve non si intreccino
|
// Verifico che le curve non si intreccino
|
||||||
pSubEdge2->GetParamAtPoint( vSyncLines.end()[-2].second, dU0, TOL) ;
|
pSubEdge2->GetParamAtPoint( vSyncLines[0].second, dU0, TOL) ;
|
||||||
pSubEdge2->GetParamAtPoint( vSyncLines.end()[-1].second, dU1, TOL) ;
|
pSubEdge2->GetParamAtPoint( vSyncLines[1].second, dU1, TOL) ;
|
||||||
if ( dU0 > dU1 - EPS_SMALL)
|
if ( dU0 > dU1 - EPS_SMALL)
|
||||||
vSyncLines.pop_back() ; // lascio solo la prima... ( bisognerebbe scegliere quale lasciare con un criterio migliore ?)
|
vSyncLines.pop_back() ; // lascio solo la prima... ( bisognerebbe scegliere quale lasciare con un criterio migliore ?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// se ne ho due tengo solo la prima
|
|
||||||
if ( ssize( vSyncLines) - nLastSync == 2)
|
|
||||||
vSyncLines.pop_back() ;
|
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6338,11 +6420,11 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
|||||||
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
|
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
|
||||||
dLenCurr1 = Clamp( dLenPrev1 + dMyDist, 0., dLen1) ;
|
dLenCurr1 = Clamp( dLenPrev1 + dMyDist, 0., dLen1) ;
|
||||||
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
|
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
|
||||||
// se sono abbastanza vicino ad una joint allora prendo quel punto
|
//// se sono abbastanza vicino ad una joint allora prendo quel punto
|
||||||
double dUClosestJoint1 = round( dUCurr1) ;
|
//double dUClosestJoint1 = round( dUCurr1) ;
|
||||||
double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
|
//double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
|
||||||
if ( abs( dLenCurr1 - dLenAlt1) < 1)
|
//if ( abs( dLenCurr1 - dLenAlt1) < 1)
|
||||||
dUCurr1 = dUClosestJoint1 ;
|
// dUCurr1 = dUClosestJoint1 ;
|
||||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||||
vtCurr1.Normalize() ;
|
vtCurr1.Normalize() ;
|
||||||
|
|
||||||
@@ -6355,17 +6437,14 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
|||||||
|
|
||||||
GetIsoPointOnSecondCurve( pCrvEdge1, pCrvEdge2, dUCurr1, dUCurr2, dMyDist, dUPrev2, dLenPrev2, dLenCurr2, dLen2) ;
|
GetIsoPointOnSecondCurve( pCrvEdge1, pCrvEdge2, dUCurr1, dUCurr2, dMyDist, dUPrev2, dLenPrev2, dLenCurr2, dLen2) ;
|
||||||
|
|
||||||
//////////////////////////N.B.: se si aggiunge questo pezzo bisogna anche gestire il fatto che i punti precedentemente aggiunti potrebbero non stare più sulla curva modificata!!!
|
|
||||||
//// verifico se sono vicino ad una joint esistente allora modifico la curva 2
|
//// verifico se sono vicino ad una joint esistente allora modifico la curva 2
|
||||||
//double dUClosestJoint2 = round( dUCurr2) ;
|
//double dUClosestJoint2 = round( dUCurr2) ;
|
||||||
//double dLenAlt2 = 0 ; pCrvEdge2->GetLengthAtParam( dUClosestJoint2, dLenAlt2) ;
|
//double dLenAlt2 = 0 ; pCrvEdge2->GetLengthAtParam( dUClosestJoint2, dLenAlt2) ;
|
||||||
//if ( abs( dLenCurr2 - dLenAlt2) < 1) {
|
//if ( abs( dLenCurr1 - dLenAlt2) < 1) {
|
||||||
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptNewJoint) ;
|
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUClosestJoint2, ICurve::FROM_MINUS, ptNewJoint) ;
|
||||||
// if ( pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint))
|
// pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint) ;
|
||||||
// dUCurr2 = dUClosestJoint2 ;
|
// dUCurr2 = dUClosestJoint2 ;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
|
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
|
||||||
|
|
||||||
#if DEBUG_SYNCLINES
|
#if DEBUG_SYNCLINES
|
||||||
@@ -6376,6 +6455,10 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
|||||||
#endif
|
#endif
|
||||||
vSyncLines.emplace_back( ptCurr1, ptCurr2) ;
|
vSyncLines.emplace_back( ptCurr1, ptCurr2) ;
|
||||||
|
|
||||||
|
//// Inserisco le curve di sincronizzazione nel Layer di destinazine
|
||||||
|
//PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( ptCurr1, ptCurr2) ;
|
||||||
|
//pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||||
|
|
||||||
// --- Analisi degli spigoli all'interno della Quadrangolazione corrente ---
|
// --- Analisi degli spigoli all'interno della Quadrangolazione corrente ---
|
||||||
// NB. Non è sempre detto che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)...
|
// NB. Non è sempre detto che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)...
|
||||||
// Pertanto la Bezier Ruled ricavata non è detto che sia in grado di approssimare lo spigolo correttamente, potrebbe sdondarlo
|
// Pertanto la Bezier Ruled ricavata non è detto che sia in grado di approssimare lo spigolo correttamente, potrebbe sdondarlo
|
||||||
@@ -6383,21 +6466,25 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
|||||||
PtrOwner<ICurveComposite> pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ;
|
PtrOwner<ICurveComposite> pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ;
|
||||||
BIPNTVECTOR vEdgeSyncLines ;
|
BIPNTVECTOR vEdgeSyncLines ;
|
||||||
ManageEdgesInQuadrangulation( pCrvQuad1, pCrvQuad2, vEdgeSyncLines) ;
|
ManageEdgesInQuadrangulation( pCrvQuad1, pCrvQuad2, vEdgeSyncLines) ;
|
||||||
|
//for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
|
||||||
|
// PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vEdgeSyncLines[i].first, vEdgeSyncLines[i].second) ;
|
||||||
|
// int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||||
|
// pGeomDB->SetMaterial( nNewId, GREEN) ;
|
||||||
|
//}
|
||||||
|
|
||||||
// --- Aggiunta di Linee di Sync all'interno della Quandrangolazione corrente ---
|
// --- Aggiunta di Linee di Sync all'interno della Quandrangolazione corrente ---
|
||||||
// Perchè parametrizzando per la lunghezza i SottoTratti ricavati, nel caso di elevate variazioni angolari tra l'inizio e la fine
|
// Perchè parametrizzando per la lunghezza i SottoTratti ricavati, nel caso di elevate variazioni angolari tra l'inizio e la fine
|
||||||
// ( tra due curva di Sync) si potrebbero generare delle torsioni non volute
|
// ( tra due curva di Sync) si potrebbero generare delle torsioni non volute
|
||||||
// -->! NB. Queste linee vengono create considerando le SubQuadrangolazioni con gli Spigoli. !<--
|
// -->! NB. Queste linee vengono create considerando le SubQuadrangolazioni con gli Spigoli. !<--
|
||||||
BIPNTVECTOR vTwistSyncLines ;
|
BIPNTVECTOR vTwistSyncLines ;
|
||||||
bool bEraseLastIso = false ;
|
|
||||||
if ( vEdgeSyncLines.empty())
|
if ( vEdgeSyncLines.empty())
|
||||||
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines, bEraseLastIso) ;
|
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines) ;
|
||||||
else {
|
else {
|
||||||
BIPOINT SyncLinePrev, SyncLineNext ;
|
BIPOINT SyncLinePrev, SyncLineNext ;
|
||||||
pCrvQuad1->GetStartPoint( SyncLinePrev.first) ;
|
pCrvQuad1->GetStartPoint( SyncLinePrev.first) ;
|
||||||
pCrvQuad2->GetStartPoint( SyncLinePrev.second) ;
|
pCrvQuad2->GetStartPoint( SyncLinePrev.second) ;
|
||||||
for ( int i = 0 ; i <= ssize( vEdgeSyncLines) ; ++ i) {
|
for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
|
||||||
if ( i == ssize( vEdgeSyncLines)) {
|
if ( i == ssize( vEdgeSyncLines) - 1) {
|
||||||
pCrvQuad1->GetEndPoint( SyncLineNext.first) ;
|
pCrvQuad1->GetEndPoint( SyncLineNext.first) ;
|
||||||
pCrvQuad2->GetEndPoint( SyncLineNext.second) ;
|
pCrvQuad2->GetEndPoint( SyncLineNext.second) ;
|
||||||
}
|
}
|
||||||
@@ -6412,21 +6499,13 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
|||||||
pCrvQuad1->GetParamAtPoint( SyncLineNext.first, dUE1) ;
|
pCrvQuad1->GetParamAtPoint( SyncLineNext.first, dUE1) ;
|
||||||
pCrvQuad2->GetParamAtPoint( SyncLineNext.second, dUE2) ;
|
pCrvQuad2->GetParamAtPoint( SyncLineNext.second, dUE2) ;
|
||||||
PtrOwner<ICurveComposite> pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ;
|
PtrOwner<ICurveComposite> pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ;
|
||||||
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUS2, dUE2))) ;
|
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUE1, dUE2))) ;
|
||||||
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines, bEraseLastIso) ;
|
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines) ;
|
||||||
// Aggiorno i parametri
|
// Aggiorno i parametri
|
||||||
SyncLinePrev = SyncLineNext ;
|
SyncLinePrev = SyncLineNext ;
|
||||||
}
|
}
|
||||||
bEraseLastIso = false ;
|
|
||||||
}
|
}
|
||||||
if ( bEraseLastIso) {
|
// aggiungo le nuove curve ( non importa che siano in ordine di parametro)
|
||||||
vSyncLines.pop_back() ;
|
|
||||||
double dQuadLen1 ; pCrvQuad1->GetLengthAtPoint( vTwistSyncLines[0].first, dQuadLen1) ;
|
|
||||||
dLenCurr1 = dLenPrev1 + dQuadLen1 ;
|
|
||||||
double dQuadLen2 ; pCrvQuad2->GetLengthAtPoint( vTwistSyncLines[0].second, dQuadLen2) ;
|
|
||||||
dLenCurr2 = dLenPrev2 + dQuadLen2 ;
|
|
||||||
}
|
|
||||||
// aggiungo le nuove curve ( non importa che siano ordinate per parametro)
|
|
||||||
vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ;
|
vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ;
|
||||||
vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ;
|
vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ;
|
||||||
|
|
||||||
@@ -6439,6 +6518,8 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
|||||||
SaveGeoObj( vGeo, vCol, "D:\\Temp\\bezier\\ruled\\trimming\\smooth.nge") ;
|
SaveGeoObj( vGeo, vCol, "D:\\Temp\\bezier\\ruled\\trimming\\smooth.nge") ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// devo riempire vSyncLines
|
||||||
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ;
|
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6946,18 +7027,14 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
|
|||||||
if ( vIso[c].dParam0 < dLastParam0) {
|
if ( vIso[c].dParam0 < dLastParam0) {
|
||||||
if ( dLastParam0 - vIso[c].dParam0 < EPS_ZERO)
|
if ( dLastParam0 - vIso[c].dParam0 < EPS_ZERO)
|
||||||
vIso[c].dParam0 = dLastParam0 + EPS_PARAM ;
|
vIso[c].dParam0 = dLastParam0 + EPS_PARAM ;
|
||||||
else {
|
else
|
||||||
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be created with the isocurves provided") ;
|
|
||||||
return false ;
|
return false ;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( vIso[c].dParam1 < dLastParam1) {
|
if ( vIso[c].dParam1 < dLastParam1) {
|
||||||
if ( dLastParam1 - vIso[c].dParam1 < EPS_ZERO)
|
if ( dLastParam1 - vIso[c].dParam1 < EPS_ZERO)
|
||||||
vIso[c].dParam1 = dLastParam1 + EPS_PARAM ;
|
vIso[c].dParam1 = dLastParam1 + EPS_PARAM ;
|
||||||
else {
|
else
|
||||||
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be created with the isocurves provided") ;
|
|
||||||
return false ;
|
return false ;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dLastParam0 = vIso[c].dParam0 ;
|
dLastParam0 = vIso[c].dParam0 ;
|
||||||
dLastParam1 = vIso[c].dParam1 ;
|
dLastParam1 = vIso[c].dParam1 ;
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
|||||||
bool AddExtLoop( ICurve* pCrv) override ;
|
bool AddExtLoop( ICurve* pCrv) override ;
|
||||||
bool AddIntLoop( const ICurve& cCrv) override ;
|
bool AddIntLoop( const ICurve& cCrv) override ;
|
||||||
bool AddIntLoop( ICurve* pCrv) override ;
|
bool AddIntLoop( ICurve* pCrv) override ;
|
||||||
bool Cut( const Plane3d& plPlane) override ;
|
|
||||||
bool Add( const ISurfFlatRegion& Other) override ;
|
bool Add( const ISurfFlatRegion& Other) override ;
|
||||||
bool Subtract( const ISurfFlatRegion& Other) override ;
|
bool Subtract( const ISurfFlatRegion& Other) override ;
|
||||||
bool Intersect( const ISurfFlatRegion& Other) override ;
|
bool Intersect( const ISurfFlatRegion& Other) override ;
|
||||||
|
|||||||
@@ -21,99 +21,13 @@
|
|||||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||||
|
|
||||||
#define SAVELOOPS 0
|
#define SAVELOOPS 0
|
||||||
#define DEBUG_PLANE_CUT 0
|
#if SAVELOOPS
|
||||||
#if SAVELOOPS || DEBUG_PLANE_CUT
|
std::vector<IGeoObj*> vGeo ;
|
||||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||||
#include "/EgtDev/Include/EGkColor.h"
|
|
||||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
|
||||||
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
||||||
#include "CurveArc.h"
|
|
||||||
std::vector<IGeoObj*> vGeo ;
|
|
||||||
std::vector<Color> vCol ;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std ;
|
using namespace std ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
SurfFlatRegion::Cut( const Plane3d& plPlane)
|
|
||||||
{
|
|
||||||
// verifico che la superficie corrente e il piano di taglio siano validi
|
|
||||||
if ( ! IsValid() || ! plPlane.IsValid())
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// !<-- Il taglio avviene nel verso della normale
|
|
||||||
|
|
||||||
// recupero le normali del piano e della superficie
|
|
||||||
const Vector3d vtPlane = plPlane.GetVersN() ;
|
|
||||||
const Vector3d vtN = GetNormVersor() ;
|
|
||||||
// recupero il centroide e la distanza tra esso e il piano
|
|
||||||
Point3d ptCentroid ; GetCentroid( ptCentroid) ;
|
|
||||||
double dDist = DistPointPlane( ptCentroid, plPlane) ;
|
|
||||||
|
|
||||||
#if DEBUG_PLANE_CUT
|
|
||||||
vGeo.clear() ; vCol.clear() ;
|
|
||||||
CurveArc crvPlane ; crvPlane.Set( plPlane.GetPoint(), plPlane.GetVersN(), 1e5) ;
|
|
||||||
SurfFlatRegion sfrPlane ; sfrPlane.AddExtLoop( crvPlane) ;
|
|
||||||
vGeo.emplace_back( sfrPlane.Clone()) ; vCol.emplace_back( BLUE) ;
|
|
||||||
vGeo.push_back( this->Clone()) ; vCol.emplace_back( LIME) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// --- se le normali sono tra di loro parallele
|
|
||||||
if ( AreSameOrOppositeVectorApprox( vtPlane, vtN)) {
|
|
||||||
// la normale della superficie non ha importanza, basta solo verificare se la superficie si trova sopra, sotto o nel piano
|
|
||||||
// --- se la superficie giace nel piano, allora la svuoto
|
|
||||||
if ( abs( dDist) < EPS_SMALL)
|
|
||||||
Clear() ;
|
|
||||||
// --- se la superficie si trova sopra al piano, allora la svuoto
|
|
||||||
else if ( dDist > 0.)
|
|
||||||
Clear() ;
|
|
||||||
// --- se la superficie si trova sotto allora non devo fare nulla
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- essendo la superficie e il piano non paralleli, mettendomi nel sistema di riferimento della superficie posso considerare il
|
|
||||||
// piano come una linea e classificare i Loop in base al Side. Tutto ciò che si trova nel Side Left viene trimmato
|
|
||||||
Vector3d vtLineDir = vtPlane ^ vtN ;
|
|
||||||
double dSqSin = vtLineDir.SqLen() ;
|
|
||||||
if ( dSqSin < SQ_EPS_SMALL)
|
|
||||||
return false ;
|
|
||||||
Vector3d vtNProj = OrthoCompo( vtPlane, vtN) ;
|
|
||||||
Point3d ptLine = ptCentroid + vtNProj * ( - dDist / dSqSin) ; // !<-- dDist è negativa
|
|
||||||
if ( ! vtLineDir.Normalize())
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// definisco la linea di classificazione ( interna al frame della superficie)
|
|
||||||
BBox3d BBox2d ;
|
|
||||||
if ( ! GetLocalBBox( BBox2d))
|
|
||||||
return false ;
|
|
||||||
double dBoxDiam ; BBox2d.GetDiameter( dBoxDiam) ;
|
|
||||||
const double dDepth = Dist( ptLine, ptCentroid) + 2. * dBoxDiam ;
|
|
||||||
Point3d ptLineS = ptLine - dDepth * vtLineDir ;
|
|
||||||
Point3d ptLineE = ptLine + dDepth * vtLineDir ;
|
|
||||||
|
|
||||||
// definisco la regione di influenza del piano
|
|
||||||
CurveComposite CompoRect ;
|
|
||||||
CompoRect.AddPoint( ptLineS) ;
|
|
||||||
CompoRect.AddLine( ptLineS + GetRotate( vtLineDir, m_frF.VersZ(), ANG_RIGHT) * dDepth) ;
|
|
||||||
CompoRect.AddLine( ptLineE + GetRotate( vtLineDir, m_frF.VersZ(), ANG_RIGHT) * dDepth) ;
|
|
||||||
CompoRect.AddLine( ptLineE) ;
|
|
||||||
CompoRect.Close() ;
|
|
||||||
SurfFlatRegion SfrRect ;
|
|
||||||
if ( ! SfrRect.AddExtLoop( CompoRect))
|
|
||||||
return false ;
|
|
||||||
if ( AreOppositeVectorApprox( SfrRect.GetNormVersor(), m_frF.VersZ()))
|
|
||||||
SfrRect.Invert() ;
|
|
||||||
|
|
||||||
#if DEBUG_PLANE_CUT
|
|
||||||
vGeo.push_back( SfrRect.Clone()) ; vCol.emplace_back( RED) ;
|
|
||||||
SaveGeoObj( vGeo, vCol, "C:\\Temp\\SfrPlaneCut.nge") ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Classifico le curve della regione
|
|
||||||
return ( Subtract( SfrRect)) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
SurfFlatRegion::Add( const ISurfFlatRegion& Other)
|
SurfFlatRegion::Add( const ISurfFlatRegion& Other)
|
||||||
|
|||||||
+17
-43
@@ -1150,7 +1150,7 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria, double dLinTol) const
|
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria) const
|
||||||
{
|
{
|
||||||
// Verifico lo stato
|
// Verifico lo stato
|
||||||
if ( m_nStatus != OK)
|
if ( m_nStatus != OK)
|
||||||
@@ -1163,7 +1163,6 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
|||||||
|
|
||||||
// Controlli su tolleranza
|
// Controlli su tolleranza
|
||||||
dTol = max( dTol, 100 * EPS_SMALL) ;
|
dTol = max( dTol, 100 * EPS_SMALL) ;
|
||||||
double dMyLinTol = max( EPS_SMALL, dLinTol) ;
|
|
||||||
|
|
||||||
// Determino il riferimento di proiezione
|
// Determino il riferimento di proiezione
|
||||||
Frame3d frOCS ; frOCS.Set( ORIG, vtVers) ;
|
Frame3d frOCS ; frOCS.Set( ORIG, vtVers) ;
|
||||||
@@ -1183,16 +1182,14 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
|||||||
( ! bAllTria && Tria.GetN() * vtVers > EPS_ZERO)) &&
|
( ! bAllTria && Tria.GetN() * vtVers > EPS_ZERO)) &&
|
||||||
Tria.Scale( frOCS, 1, 1, 0) && Tria.GetSqMinHeight() > SQ_EPS_SMALL) {
|
Tria.Scale( frOCS, 1, 1, 0) && Tria.GetSqMinHeight() > SQ_EPS_SMALL) {
|
||||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromTriangle( Tria))) ;
|
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromTriangle( Tria))) ;
|
||||||
if ( ! IsNull( pSfrTria) && pSfrTria->IsValid()) {
|
if ( ! IsNull( pSfrTria)) {
|
||||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||||
pSfrTria->Invert() ;
|
pSfrTria->Invert() ;
|
||||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||||
if ( IsNull( pSfr))
|
if ( IsNull( pSfr))
|
||||||
pSfr.Set( pSfrTria) ;
|
pSfr.Set( pSfrTria) ;
|
||||||
else {
|
else
|
||||||
if ( ! pSfr->Add( *pSfrTria))
|
pSfr->Add( *pSfrTria) ;
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// passo al successivo
|
// passo al successivo
|
||||||
@@ -1204,18 +1201,14 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
|||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// Effettuo contro-offset
|
// Effettuo contro-offset
|
||||||
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
|
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||||
return false ;
|
|
||||||
|
|
||||||
// Recupero i contorni della regione
|
// Recupero i contorni della regione
|
||||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||||
PolyLine PL ;
|
PolyLine PL ;
|
||||||
if ( ! pSfr->ApproxLoopWithLines( i, j, dMyLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
|
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||||
vPL.clear() ;
|
vPL.emplace_back( PL) ;
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
vPL.emplace_back( PL) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1224,7 +1217,7 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria, double dLinTol) const
|
SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria) const
|
||||||
{
|
{
|
||||||
// Verifico lo stato
|
// Verifico lo stato
|
||||||
if ( m_nStatus != OK)
|
if ( m_nStatus != OK)
|
||||||
@@ -1237,7 +1230,6 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
|||||||
|
|
||||||
// Controlli su tolleranza
|
// Controlli su tolleranza
|
||||||
dTol = max( dTol, 100 * EPS_SMALL) ;
|
dTol = max( dTol, 100 * EPS_SMALL) ;
|
||||||
double dMyLinTol = max( EPS_SMALL, dLinTol) ;
|
|
||||||
|
|
||||||
// Determino il riferimento di proiezione
|
// Determino il riferimento di proiezione
|
||||||
Frame3d frOCS ; frOCS.Set( plPlane.GetPoint(), vtVers) ;
|
Frame3d frOCS ; frOCS.Set( plPlane.GetPoint(), vtVers) ;
|
||||||
@@ -1261,16 +1253,14 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
|||||||
// lo proietto sul piano e creo la regione
|
// lo proietto sul piano e creo la regione
|
||||||
if ( pgTria.Scale( frOCS, 1, 1, 0)) {
|
if ( pgTria.Scale( frOCS, 1, 1, 0)) {
|
||||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
||||||
if ( ! IsNull( pSfrTria) && pSfrTria->IsValid()) {
|
if ( ! IsNull( pSfrTria)) {
|
||||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||||
pSfrTria->Invert() ;
|
pSfrTria->Invert() ;
|
||||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||||
if ( IsNull( pSfr))
|
if ( IsNull( pSfr))
|
||||||
pSfr.Set( pSfrTria) ;
|
pSfr.Set( pSfrTria) ;
|
||||||
else {
|
else
|
||||||
if ( ! pSfr->Add( *pSfrTria))
|
pSfr->Add( *pSfrTria) ;
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1284,18 +1274,14 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
|||||||
return true ;
|
return true ;
|
||||||
|
|
||||||
// Effettuo contro-offset
|
// Effettuo contro-offset
|
||||||
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
|
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||||
return false ;
|
|
||||||
|
|
||||||
// Recupero i contorni della regione
|
// Recupero i contorni della regione
|
||||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||||
PolyLine PL ;
|
PolyLine PL ;
|
||||||
if ( ! pSfr->ApproxLoopWithLines( i, j, dMyLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
|
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||||
vPL.clear() ;
|
vPL.emplace_back( PL) ;
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
vPL.emplace_back( PL) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3824,19 +3810,12 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
|||||||
BBox3d b3Box ;
|
BBox3d b3Box ;
|
||||||
PtrOwner<ISurfTriMesh> pStmShell ;
|
PtrOwner<ISurfTriMesh> pStmShell ;
|
||||||
} ;
|
} ;
|
||||||
// vettore di shell con vettori dei propri triangoli (per accelerare nei casi degeneri)
|
|
||||||
INTMATRIX mShellTria( m_nShells) ;
|
|
||||||
for ( int i = 0 ; i < ssize( m_vTria) ; ++ i) {
|
|
||||||
if ( m_vTria[i].nShell < m_nShells)
|
|
||||||
mShellTria[m_vTria[i].nShell].push_back( i) ;
|
|
||||||
}
|
|
||||||
// classificazione delle shell
|
|
||||||
vector<SHELLINFO> vOuterShells ;
|
vector<SHELLINFO> vOuterShells ;
|
||||||
vector<SHELLINFO> vInnerShells ;
|
vector<SHELLINFO> vInnerShells ;
|
||||||
INTVECTOR vOpenShells ;
|
INTVECTOR vOpenShells ;
|
||||||
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
|
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
|
||||||
// se la shell è chiusa
|
// se la shell è chiusa
|
||||||
if ( ssize( mShellTria[nSh]) >= 4 && IsShellClosed( nSh)) {
|
if ( IsShellClosed( nSh)) {
|
||||||
// creo una superficie clonata dalla shell
|
// creo una superficie clonata dalla shell
|
||||||
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
|
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
|
||||||
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
||||||
@@ -3848,9 +3827,7 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
|||||||
BBox3d b3Box ;
|
BBox3d b3Box ;
|
||||||
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
|
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
|
||||||
// la inserisco nel vettore opportuno
|
// la inserisco nel vettore opportuno
|
||||||
if ( abs( dVol) < 1 * 1 * EPS_SMALL)
|
if ( dVol > 0)
|
||||||
vOpenShells.push_back( nSh) ;
|
|
||||||
else if ( dVol > 0)
|
|
||||||
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||||
else
|
else
|
||||||
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||||
@@ -4002,7 +3979,6 @@ SurfTriMesh::IsShellClosed( int nShell) const
|
|||||||
return false ;
|
return false ;
|
||||||
// ciclo sui triangoli della shell
|
// ciclo sui triangoli della shell
|
||||||
bool bClosed = true ;
|
bool bClosed = true ;
|
||||||
int nTriaCnt = 0 ;
|
|
||||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||||
// se triangolo non cancellato e della shell
|
// se triangolo non cancellato e della shell
|
||||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||||
@@ -4013,12 +3989,10 @@ SurfTriMesh::IsShellClosed( int nShell) const
|
|||||||
bClosed = false ;
|
bClosed = false ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
++ nTriaCnt ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// restituisco il risultato
|
// restituisco il risultato
|
||||||
return ( bClosed && nTriaCnt >= 4) ;
|
return bClosed ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|||||||
+2
-3
@@ -16,7 +16,6 @@
|
|||||||
#include "ObjGraphicsMgr.h"
|
#include "ObjGraphicsMgr.h"
|
||||||
#include "DllMain.h"
|
#include "DllMain.h"
|
||||||
#include "GeoObjRW.h"
|
#include "GeoObjRW.h"
|
||||||
#include "GeoConst.h"
|
|
||||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||||
#include "/EgtDev/Include/EGkHashGrids3d.h"
|
#include "/EgtDev/Include/EGkHashGrids3d.h"
|
||||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||||
@@ -296,8 +295,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
|||||||
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
|
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
|
||||||
SurfTriMesh* CloneTriangle( int nT) const override ;
|
SurfTriMesh* CloneTriangle( int nT) const override ;
|
||||||
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
|
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
|
||||||
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false, double dLinTol = LIN_TOL_STD) const override ;
|
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||||
bool GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false, double dLinTol = LIN_TOL_STD) const override ;
|
bool GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||||
int GetFacetCount( void) const override ;
|
int GetFacetCount( void) const override ;
|
||||||
int GetFacetSize( void) const override
|
int GetFacetSize( void) const override
|
||||||
{ return int( m_vFacet.size()) ; }
|
{ return int( m_vFacet.size()) ; }
|
||||||
|
|||||||
+42
-127
@@ -3533,11 +3533,10 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static bool
|
static bool
|
||||||
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
|
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
|
||||||
const Plane3d& plStart, const Plane3d& plEnd, const Vector3d vtAuxStart, const Vector3d vtAuxEnd,
|
const Plane3d& plStart, const Plane3d& plEnd, double dLinTol,
|
||||||
double dLinTol, BIPNTVECTOR& vBiPts)
|
BIPNTVECTOR& vBiPts)
|
||||||
{
|
{
|
||||||
vBiPts.clear() ;
|
vBiPts.clear() ;
|
||||||
const double dLinAngTol = 15 * EPS_SMALL ; // tolleranza sulla lunghezza della corda dell'angolo di tolleranza
|
|
||||||
|
|
||||||
// Verifico che le curve siano valide
|
// Verifico che le curve siano valide
|
||||||
if ( pGuide == nullptr || ! pGuide->IsValid() ||
|
if ( pGuide == nullptr || ! pGuide->IsValid() ||
|
||||||
@@ -3567,134 +3566,52 @@ InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICur
|
|||||||
// Interpolo le normali dei piani rispetto a tale valore
|
// Interpolo le normali dei piani rispetto a tale valore
|
||||||
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
|
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
|
||||||
vtN.Normalize() ;
|
vtN.Normalize() ;
|
||||||
Vector3d vtAux = Media( vtAuxStart, vtAuxEnd, dInterPar) ; vtAux.Normalize() ;
|
|
||||||
// Definisco il piano di intersezione
|
// Definisco il piano di intersezione
|
||||||
Point3d ptCurr ;
|
Point3d ptCurr ;
|
||||||
if ( ! pCrv->GetEndPoint( ptCurr))
|
if ( ! pCrv->GetEndPoint( ptCurr))
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// con i piani
|
|
||||||
#if DEBUG_SYNC_INTERPOLATION
|
#if DEBUG_SYNC_INTERPOLATION
|
||||||
Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
|
Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
|
||||||
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
|
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
|
||||||
VT.emplace_back( Release( frCurr)) ;
|
VT.emplace_back( Release( frCurr)) ;
|
||||||
VC.emplace_back( WHITE) ;
|
VC.emplace_back( WHITE) ;
|
||||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||||
#endif
|
#endif
|
||||||
// Recupero il parametro di intersezione tra la curva e il piano
|
// Recupero il parametro di intersezione tra la curva e il piano
|
||||||
#if DEBUG_SYNC_INTERPOLATION
|
#if 0
|
||||||
if ( false) {
|
VT.clear() ; VC.clear() ;
|
||||||
VT.clear() ; VC.clear() ;
|
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
|
||||||
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
|
VT.emplace_back( Release( PT)) ;
|
||||||
VT.emplace_back( Release( PT)) ;
|
VC.emplace_back( AQUA) ;
|
||||||
VC.emplace_back( AQUA) ;
|
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
|
||||||
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
|
VECT->ChangeBase( ptCurr) ;
|
||||||
VECT->ChangeBase( ptCurr) ;
|
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
|
||||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
|
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
|
||||||
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
|
pSfrPlane->AddExtLoop( Release( pArc)) ;
|
||||||
pSfrPlane->AddExtLoop( Release( pArc)) ;
|
VT.emplace_back( Release( pSfrPlane)) ;
|
||||||
VT.emplace_back( Release( pSfrPlane)) ;
|
VC.emplace_back( Color( 0., 0., 0., .5)) ;
|
||||||
VC.emplace_back( Color( 0., 0., 0., .5)) ;
|
VT.emplace_back( Release( VECT)) ;
|
||||||
VT.emplace_back( Release( VECT)) ;
|
VC.emplace_back( BLUE) ;
|
||||||
VC.emplace_back( BLUE) ;
|
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
VC.emplace_back( WHITE) ;
|
||||||
VC.emplace_back( WHITE) ;
|
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
|
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
|
||||||
bool bFound = false ;
|
if ( IntCP.GetIntersCount() == 0)
|
||||||
if ( IntCP.GetIntersCount() != 0) {
|
return false ; // ambiguità
|
||||||
// Recupero il punto della prima intersezione trovata
|
// Recupero il punto della prima intersezione trovata
|
||||||
Point3d ptIntClosest ;
|
Point3d ptInt ;
|
||||||
double dPar ;
|
double dPar ;
|
||||||
IntCP.GetIntersPointNearTo( ptCurr, ptIntClosest, dPar) ;
|
if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar))
|
||||||
// verifico che sia allineato con la direzione che dovrebbe avere
|
return false ;
|
||||||
Vector3d vtDir = ptIntClosest - ptCurr ;
|
#if DEBUG_SYNC_INTERPOLATION
|
||||||
vtDir.Normalize() ;
|
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ;
|
||||||
double dDiff = (vtDir - vtAux).Len() ;
|
VT.emplace_back( Release( ptG)) ;
|
||||||
if ( dDiff < dLinAngTol) {
|
VC.emplace_back( WHITE) ;
|
||||||
#if DEBUG_SYNC_INTERPOLATION
|
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||||
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptIntClosest) ;
|
#endif
|
||||||
VT.emplace_back( Release( ptG)) ;
|
// Memorizzo tale punto
|
||||||
VC.emplace_back( WHITE) ;
|
vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ;
|
||||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
|
||||||
#endif
|
|
||||||
//Memorizzo tale punto
|
|
||||||
vBiPts.emplace_back( make_pair( ptCurr, ptIntClosest)) ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
else if ( IntCP.GetIntersCount() > 1) {
|
|
||||||
double dMinDiff = INFINITO ;
|
|
||||||
Point3d ptBest ;
|
|
||||||
for ( int j = 0 ; j < IntCP.GetIntersCount() ; ++j) {
|
|
||||||
IntCrvPlnInfo icpi ; IntCP.GetIntCrvPlnInfo( j, icpi) ;
|
|
||||||
Point3d ptInt = icpi.Ici->ptI ;
|
|
||||||
double dDiff = ( ptInt - ptCurr).Len() ;
|
|
||||||
if ( dDiff < dMinDiff) {
|
|
||||||
dMinDiff = dDiff ;
|
|
||||||
ptBest = ptInt ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( dMinDiff < dLinAngTol)
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! bFound) {
|
|
||||||
// applico la direzione desiderata nel punto corrente della guida
|
|
||||||
// calcolo la lunghezza dell'isocurva in quella zona
|
|
||||||
Point3d ptS1, ptS2 ;
|
|
||||||
pGuide->GetStartPoint( ptS1) ;
|
|
||||||
pOtherGuide->GetStartPoint( ptS2);
|
|
||||||
double dDistRef = Dist( ptS1, ptS2) ;
|
|
||||||
double dParamOther = -1. ;
|
|
||||||
int nFlag = -1 ;
|
|
||||||
Point3d ptEnd = ptCurr + (vtAux * dDistRef) ;
|
|
||||||
if ( ! DistPointCurve( ptEnd, *pOtherGuide).GetParamAtMinDistPoint( 0, dParamOther, nFlag))
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// nell'intorno del più vicino, cerco l'isocurva più vicina alla direzione desiderata
|
|
||||||
Point3d ptBest ;
|
|
||||||
double dMinDiff = INFINITO ;
|
|
||||||
double dSearchLen = 3. ;
|
|
||||||
double dStepLen = 0.1 ;
|
|
||||||
double dCurrLenOther ; pOtherGuide->GetLengthAtParam( dParamOther, dCurrLenOther) ;
|
|
||||||
double dLenOther ; pOtherGuide->GetLength( dLenOther) ;
|
|
||||||
dCurrLenOther -= dSearchLen ;
|
|
||||||
dCurrLenOther = Clamp( dCurrLenOther, 0., dLenOther) ;
|
|
||||||
for ( int j = 0 ; j < 2 * dSearchLen / dStepLen ; ++j) {
|
|
||||||
dCurrLenOther += j * dStepLen ;
|
|
||||||
if ( dCurrLenOther > dLenOther)
|
|
||||||
break ;
|
|
||||||
double dCurrParOther = 0 ; pOtherGuide->GetParamAtLength( dCurrLenOther, dCurrParOther) ;
|
|
||||||
Point3d ptCurrOther ; pOtherGuide->GetPointD1D2( dCurrParOther, ICurve::FROM_MINUS, ptCurrOther) ;
|
|
||||||
Vector3d vtDir = ptCurrOther - ptCurr ; vtDir.Normalize() ;
|
|
||||||
double dDiff = ( vtDir - vtAux).Len() ;
|
|
||||||
if ( dDiff < dMinDiff) {
|
|
||||||
dMinDiff = dDiff ;
|
|
||||||
ptBest = ptCurrOther ;
|
|
||||||
}
|
|
||||||
#if DEBUG_SYNC_INTERPOLATION
|
|
||||||
VT.clear() ;
|
|
||||||
VC.clear() ;
|
|
||||||
VT.emplace_back( pGuide->Clone()) ;
|
|
||||||
VC.emplace_back( BLUE) ;
|
|
||||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
|
||||||
VC.emplace_back( BLUE) ;
|
|
||||||
PtrOwner<IGeoVector3d> vtFirst( CreateGeoVector3d()) ; vtFirst->Set( -vtN * 12, ptCurrOther) ;
|
|
||||||
VT.emplace_back( Release( vtFirst)) ;
|
|
||||||
VC.emplace_back( AQUA) ;
|
|
||||||
PtrOwner<IGeoVector3d> vtCurr( CreateGeoVector3d()) ; vtCurr->Set( -vtDir * 12, ptCurrOther) ;
|
|
||||||
VT.emplace_back( Release( vtCurr)) ;
|
|
||||||
VC.emplace_back( WHITE) ;
|
|
||||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if ( dMinDiff < 2 * dLinAngTol)
|
|
||||||
vBiPts.emplace_back( make_pair( ptCurr, ptBest)) ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
@@ -4149,18 +4066,18 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
|||||||
Vector3d vtStart1, vtStart2 ;
|
Vector3d vtStart1, vtStart2 ;
|
||||||
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
|
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
|
||||||
return false ;
|
return false ;
|
||||||
Vector3d vtAuxStart = ptE1 - ptS1 ; vtAuxStart.Normalize() ;
|
Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ;
|
||||||
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
|
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
|
||||||
Vector3d vtN = OrthoCompo( vtMTan, vtAuxStart) ; vtN.Normalize() ;
|
Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
|
||||||
Plane3d plStart ;
|
Plane3d plStart ;
|
||||||
if ( ! plStart.Set( ptS1, vtN))
|
if ( ! plStart.Set( ptS1, vtN))
|
||||||
return false ;
|
return false ;
|
||||||
Vector3d vtEnd1, vtEnd2 ;
|
Vector3d vtEnd1, vtEnd2 ;
|
||||||
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
|
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
|
||||||
return false ;
|
return false ;
|
||||||
Vector3d vtAuxEnd = ptE2 - ptS2 ; vtAuxEnd.Normalize() ;
|
vtAux = ptE2 - ptS2 ; vtAux.Normalize() ;
|
||||||
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
|
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
|
||||||
vtN = OrthoCompo( vtMTan, vtAuxEnd) ; vtN.Normalize() ;
|
vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
|
||||||
Plane3d plEnd ;
|
Plane3d plEnd ;
|
||||||
if ( ! plEnd.Set( ptS2, vtN))
|
if ( ! plEnd.Set( ptS2, vtN))
|
||||||
return false ;
|
return false ;
|
||||||
@@ -4179,15 +4096,13 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
|||||||
|
|
||||||
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2
|
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2
|
||||||
BIPNTVECTOR vBiPts1 ;
|
BIPNTVECTOR vBiPts1 ;
|
||||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts1))
|
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1))
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
vtAuxStart *= -1 ;
|
|
||||||
vtAuxEnd *= -1 ;
|
|
||||||
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1
|
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1
|
||||||
BIPNTVECTOR vBiPts2 ;
|
BIPNTVECTOR vBiPts2 ;
|
||||||
//if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts2))
|
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2))
|
||||||
// return false ;
|
return false ;
|
||||||
|
|
||||||
// Restituisco le Curve di Sincronizzazione
|
// Restituisco le Curve di Sincronizzazione
|
||||||
// [Da Bordo 1 a Bordo 2 originale]
|
// [Da Bordo 1 a Bordo 2 originale]
|
||||||
|
|||||||
+4
-4
@@ -884,7 +884,7 @@ VolZmap::CheckMapConnection( void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Numero massimo di thread
|
// Numero massimo di thread
|
||||||
int nThreadMax = max( 1, int( thread::hardware_concurrency())) ;
|
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||||
// Ciclo sui dexel lungo Z
|
// Ciclo sui dexel lungo Z
|
||||||
for ( int tI = 0 ; tI < m_nNx[0] ; ++ tI) {
|
for ( int tI = 0 ; tI < m_nNx[0] ; ++ tI) {
|
||||||
for ( int tJ = 0 ; tJ < m_nNy[0] ; ++ tJ) {
|
for ( int tJ = 0 ; tJ < m_nNy[0] ; ++ tJ) {
|
||||||
@@ -1572,7 +1572,7 @@ VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
|
|||||||
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
||||||
|
|
||||||
// numero massimo di thread
|
// numero massimo di thread
|
||||||
int nThreadMax = max( 1, int( thread::hardware_concurrency())) ;
|
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||||
vector<future<bool>> vRes ;
|
vector<future<bool>> vRes ;
|
||||||
vRes.resize( nThreadMax) ;
|
vRes.resize( nThreadMax) ;
|
||||||
// se dimensione griglia in X maggiore di dimensione Y
|
// se dimensione griglia in X maggiore di dimensione Y
|
||||||
@@ -1660,7 +1660,7 @@ VolZmap::SubtractSurfTm( const ISurfTriMesh* pStm)
|
|||||||
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
||||||
|
|
||||||
// numero massimo di thread
|
// numero massimo di thread
|
||||||
int nThreadMax = max( 1, int( thread::hardware_concurrency())) ;
|
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||||
vector<future<bool>> vRes ;
|
vector<future<bool>> vRes ;
|
||||||
vRes.resize( nThreadMax) ;
|
vRes.resize( nThreadMax) ;
|
||||||
// se dimensione griglia in X maggiore di dimensione Y
|
// se dimensione griglia in X maggiore di dimensione Y
|
||||||
@@ -2267,7 +2267,7 @@ VolZmap::IsBox( void)
|
|||||||
if ( m_nMapNum == 1)
|
if ( m_nMapNum == 1)
|
||||||
return false ;
|
return false ;
|
||||||
// Numero massimo di thread per il calcolo parallelo.
|
// Numero massimo di thread per il calcolo parallelo.
|
||||||
int nThreadMax = max( 1, int( thread::hardware_concurrency())) ;
|
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||||
// Disponibile un solo thread
|
// Disponibile un solo thread
|
||||||
if ( nThreadMax == 1) {
|
if ( nThreadMax == 1) {
|
||||||
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
|
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
|
||||||
|
|||||||
@@ -37,26 +37,6 @@ struct AppliedVector {
|
|||||||
int nPropIndex ;
|
int nPropIndex ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
struct IntersToCheck {
|
|
||||||
Point3d ptInters ;
|
|
||||||
Vector3d vtN ;
|
|
||||||
double dU ;
|
|
||||||
int nG ;
|
|
||||||
int nI ;
|
|
||||||
int nJ ;
|
|
||||||
IntersToCheck( const Point3d& _ptI, const Vector3d& _vtN, double _dU, int _nG, int _nI, int _nJ) :
|
|
||||||
ptInters( _ptI), vtN( _vtN), dU( _dU), nG( _nG), nI( _nI), nJ( _nJ) { ;}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<IntersToCheck> INTTOCHECKVEC ;
|
|
||||||
|
|
||||||
struct Neigh { // 6 7 8
|
|
||||||
double nI ; // 3 s 5
|
|
||||||
double nJ ; // 0 1 2
|
|
||||||
int nN ; // n-esimo vicino di uno spillone : numerati così
|
|
||||||
Neigh( double _nI, double _nJ, int _nN) : nI( _nI), nJ( _nJ), nN( _nN) { ;}
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class VolZmap : public IVolZmap, public IGeoObjRW
|
class VolZmap : public IVolZmap, public IGeoObjRW
|
||||||
{
|
{
|
||||||
@@ -104,7 +84,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
|||||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr, bool bForceClosed = false) override ;
|
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ;
|
||||||
int GetBlockCount( void) const override ;
|
int GetBlockCount( void) const override ;
|
||||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||||
@@ -413,6 +393,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
|||||||
double& dU1, double& dU2) const ;
|
double& dU1, double& dU2) const ;
|
||||||
bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
||||||
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
||||||
|
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||||
|
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||||
|
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
|
||||||
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||||
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
|
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
|
||||||
bool bTapLow, bool bTapUp,
|
bool bTapLow, bool bTapUp,
|
||||||
@@ -483,15 +466,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
|||||||
bool CDeSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise = false) const ;
|
bool CDeSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise = false) const ;
|
||||||
// Funzione per crezione solido in parallelo
|
// Funzione per crezione solido in parallelo
|
||||||
bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM, bool bForceClosed) ;
|
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||||
bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||||
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||||
bool AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHECKVEC& vIntToCheck, const Point3d& ptMapOrig,
|
|
||||||
const ISurfTriMesh& Surf, const IntersParLinesSurfTm& intPLSTM) ;
|
|
||||||
bool SearchMissingIntervals( int nMap, INTTOCHECKVEC& vIntToCheck) ;
|
|
||||||
std::vector<Neigh> GetNeighbours( int nG, int nI, int nJ, double dPar) ;
|
|
||||||
// Funzioni per Offset di superfici
|
// Funzioni per Offset di superfici
|
||||||
bool InitVolZMapOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
bool InitVolZMapOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||||
bool InitVolZMapThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
bool InitVolZMapThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||||
|
|||||||
@@ -2071,6 +2071,127 @@ VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise)
|
|||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
|
||||||
|
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||||
|
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||||
|
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
|
||||||
|
{
|
||||||
|
// Porto la linea nel riferimento del cilindro
|
||||||
|
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
|
||||||
|
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
|
||||||
|
|
||||||
|
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||||
|
int nBasInt = 0 ;
|
||||||
|
if ( abs( vtV.z) > EPS_ZERO) {
|
||||||
|
// le linee tangenti al cilindro non sono considerate intersecanti
|
||||||
|
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||||
|
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
|
||||||
|
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||||
|
nBasInt += 1 ;
|
||||||
|
vtN1 = Z_AX ;
|
||||||
|
}
|
||||||
|
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
|
||||||
|
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||||
|
nBasInt += 2 ;
|
||||||
|
vtN2 = - Z_AX ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||||
|
if ( nBasInt == 3) {
|
||||||
|
// Porto i punti e i versori nel riferimento globale
|
||||||
|
ptInt1.ToGlob( CylFrame) ;
|
||||||
|
vtN1.ToGlob( CylFrame) ;
|
||||||
|
ptInt2.ToGlob( CylFrame) ;
|
||||||
|
vtN2.ToGlob( CylFrame) ;
|
||||||
|
// Trovate intersezioni
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determino le intersezioni con la superficie laterale del cilindro
|
||||||
|
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
|
||||||
|
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
|
||||||
|
vtV.x * vtV.x + vtV.y * vtV.y} ;
|
||||||
|
DBLVECTOR vdRoots ;
|
||||||
|
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||||
|
|
||||||
|
// Epsilon per piani di tappo
|
||||||
|
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
|
||||||
|
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
|
||||||
|
|
||||||
|
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||||
|
if ( nRoot == 2) {
|
||||||
|
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
|
||||||
|
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
|
||||||
|
-- nRoot ;
|
||||||
|
}
|
||||||
|
if ( nRoot >= 1) {
|
||||||
|
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
|
||||||
|
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
|
||||||
|
if ( nRoot == 2)
|
||||||
|
vdRoots[0] = vdRoots[1] ;
|
||||||
|
-- nRoot ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||||
|
if ( nRoot == 2) {
|
||||||
|
// Punti di intersezione con la superficie del cilindro
|
||||||
|
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||||
|
ptInt2 = ptP + vdRoots[1] * vtV ;
|
||||||
|
// Determino le normali
|
||||||
|
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
|
||||||
|
vtN1.Normalize() ;
|
||||||
|
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
|
||||||
|
vtN2.Normalize() ;
|
||||||
|
// Porto i punti e i versori nel riferimento globale
|
||||||
|
ptInt1.ToGlob( CylFrame) ;
|
||||||
|
vtN1.ToGlob( CylFrame) ;
|
||||||
|
ptInt2.ToGlob( CylFrame) ;
|
||||||
|
vtN2.ToGlob( CylFrame) ;
|
||||||
|
// Trovate intersezioni
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||||
|
else if ( nRoot == 1) {
|
||||||
|
// Se piano superiore
|
||||||
|
if ( nBasInt == 2) {
|
||||||
|
// Punto di intersezione
|
||||||
|
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||||
|
// Normale alla superficie del cilindro verso l'interno
|
||||||
|
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
|
||||||
|
vtN1.Normalize() ;
|
||||||
|
}
|
||||||
|
// altrimenti piano inferiore
|
||||||
|
else if ( nBasInt == 1) {
|
||||||
|
// Punto di intersezione
|
||||||
|
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||||
|
// Normale alla superficie del cilindro verso l'interno
|
||||||
|
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
|
||||||
|
vtN2.Normalize() ;
|
||||||
|
}
|
||||||
|
// altrimenti niente
|
||||||
|
else
|
||||||
|
return false ;
|
||||||
|
// Porto i punti e i versori nel riferimento globale
|
||||||
|
ptInt1.ToGlob( CylFrame) ;
|
||||||
|
vtN1.ToGlob( CylFrame) ;
|
||||||
|
ptInt2.ToGlob( CylFrame) ;
|
||||||
|
vtN2.ToGlob( CylFrame) ;
|
||||||
|
// Trovate intersezioni
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nessuna soluzione : nessuna intersezione
|
||||||
|
else
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z.
|
// Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z.
|
||||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||||
|
|||||||
+10
-640
@@ -19,10 +19,8 @@
|
|||||||
#include "GeoConst.h"
|
#include "GeoConst.h"
|
||||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
|
||||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <ranges>
|
|
||||||
|
|
||||||
using namespace std ;
|
using namespace std ;
|
||||||
|
|
||||||
@@ -544,7 +542,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM, bool bForceClosed)
|
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
|
||||||
{
|
{
|
||||||
if ( nMap < 0 || nMap > 2 ||
|
if ( nMap < 0 || nMap > 2 ||
|
||||||
nInfI < 0 || nInfI > m_nNx[nMap] ||
|
nInfI < 0 || nInfI > m_nNx[nMap] ||
|
||||||
@@ -555,8 +553,6 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
|
|
||||||
double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ;
|
double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ;
|
||||||
|
|
||||||
INTTOCHECKVEC vIntToCheck ;
|
|
||||||
|
|
||||||
// Determinazione e ridimensionamento dei dexel interni alla trimesh
|
// Determinazione e ridimensionamento dei dexel interni alla trimesh
|
||||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||||
@@ -588,14 +584,6 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
|
|
||||||
int nInt = int( IntersectionResults.size()) ;
|
int nInt = int( IntersectionResults.size()) ;
|
||||||
|
|
||||||
if ( nInt == 1) {
|
|
||||||
int nT = IntersectionResults[0].nT ;
|
|
||||||
int nF = Surf.GetFacetFromTria( nT) ;
|
|
||||||
Vector3d vtN ; Surf.GetFacetNormal( nF, vtN) ;
|
|
||||||
vIntToCheck.emplace_back( IntersectionResults[0].ptI, vtN, IntersectionResults[0].dU, nMap, i, j) ;
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nPos = j * m_nNx[nMap] + i ;
|
int nPos = j * m_nNx[nMap] + i ;
|
||||||
|
|
||||||
bool bInside = false ;
|
bool bInside = false ;
|
||||||
@@ -604,16 +592,6 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
|
|
||||||
for ( int k = 0 ; k < nInt ; ++ k) {
|
for ( int k = 0 ; k < nInt ; ++ k) {
|
||||||
|
|
||||||
if ( k > 0) {
|
|
||||||
int z = k - 1 ;
|
|
||||||
// controllo se l'intersezione corrente è coincidente con la precedente, per esempio se ILTT == 4 ( intersezione su un lato di un triangolo, quindi con 2 triangoli)
|
|
||||||
// controllo anche che le proiezioni delle normali abbiano lo stesso segno rispetto allo spillone
|
|
||||||
if ( IntersectionResults[k].dU - IntersectionResults[z].dU < EPS_SMALL &&
|
|
||||||
IntersectionResults[k].dCosDN - IntersectionResults[z].dCosDN < EPS_SMALL &&
|
|
||||||
IntersectionResults[k].dCosDN * IntersectionResults[z].dCosDN > 0)
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nIntType = IntersectionResults[k].nILTT ;
|
int nIntType = IntersectionResults[k].nILTT ;
|
||||||
|
|
||||||
// Se c'è intersezione
|
// Se c'è intersezione
|
||||||
@@ -623,12 +601,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
|
|
||||||
// entro nella superficie trimesh
|
// entro nella superficie trimesh
|
||||||
if ( dCos < - dCosSmall) {
|
if ( dCos < - dCosSmall) {
|
||||||
if ( bInside) {
|
|
||||||
// salvo la precedente, perché vuol dire che manca la sua uscita
|
|
||||||
// poi procedo con l'intersezione corrente
|
|
||||||
int z = k - 1 ;
|
|
||||||
vIntToCheck.emplace_back( IntersectionResults[z].ptI, vtInN, IntersectionResults[z].dU, nMap, i, j) ;
|
|
||||||
}
|
|
||||||
ptIn = IntersectionResults[k].ptI ;
|
ptIn = IntersectionResults[k].ptI ;
|
||||||
|
|
||||||
int nT = IntersectionResults[k].nT ;
|
int nT = IntersectionResults[k].nT ;
|
||||||
@@ -637,14 +610,11 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
Surf.GetFacetNormal( nF, vtInN) ;
|
Surf.GetFacetNormal( nF, vtInN) ;
|
||||||
|
|
||||||
bInside = true ;
|
bInside = true ;
|
||||||
if ( k == nInt - 1) {
|
|
||||||
// se ho un ingresso ma è l'ultima intersezione vuol dire che è spaiata
|
|
||||||
vIntToCheck.emplace_back( IntersectionResults[k].ptI, vtInN, IntersectionResults[k].dU, nMap, i, j) ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// esco dalla superficie trimesh
|
// esco dalla superficie trimesh
|
||||||
else if ( dCos > dCosSmall) {
|
else if ( dCos > dCosSmall && bInside) {
|
||||||
|
|
||||||
Point3d ptOut = IntersectionResults[k].ptI ;
|
Point3d ptOut = IntersectionResults[k].ptI ;
|
||||||
|
|
||||||
int nT = IntersectionResults[k].nT ;
|
int nT = IntersectionResults[k].nT ;
|
||||||
@@ -653,13 +623,6 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
Vector3d vtOutN ;
|
Vector3d vtOutN ;
|
||||||
Surf.GetFacetNormal( nF, vtOutN) ;
|
Surf.GetFacetNormal( nF, vtOutN) ;
|
||||||
|
|
||||||
if ( ! bInside) {
|
|
||||||
// se l'intersezione è uscente, ma non ho un'entrata allora devo salvare l'intersezione corrente, perché è andata persa la sua entrata
|
|
||||||
// procedo poi con la prossima intersezione
|
|
||||||
vIntToCheck.emplace_back( IntersectionResults[k].ptI, vtOutN, IntersectionResults[k].dU, nMap, i, j) ;
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nCurrentSize = int( m_Values[nMap][nPos].size()) ;
|
int nCurrentSize = int( m_Values[nMap][nPos].size()) ;
|
||||||
|
|
||||||
// Aggiungo un tratto al dexel
|
// Aggiungo un tratto al dexel
|
||||||
@@ -680,16 +643,6 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bForceClosed) {
|
|
||||||
if ( ! AdjustDexelThroughCracks( nMap, vtLen, vIntToCheck, ptMapOrig, Surf, intPLSTM))
|
|
||||||
return false ;
|
|
||||||
vIntToCheck.clear() ;
|
|
||||||
SearchMissingIntervals( nMap, vIntToCheck) ;
|
|
||||||
if ( ! AdjustDexelThroughCracks( nMap, vtLen, vIntToCheck, ptMapOrig, Surf, intPLSTM))
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,14 +834,11 @@ VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ,
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError, bool bForceClosed)
|
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError)
|
||||||
{
|
{
|
||||||
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
|
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
|
||||||
double dVol ;
|
double dVol ;
|
||||||
if ( ( ! Surf.IsClosed() || ! Surf.GetVolume( dVol) || dVol < 0) && ! bForceClosed)
|
if ( ! Surf.IsClosed() || ! Surf.GetVolume( dVol) || dVol < 0)
|
||||||
return false ;
|
|
||||||
|
|
||||||
if ( bForceClosed && ! bTriDex)
|
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// Assegno la dimensione della mappa 1 o 3
|
// Assegno la dimensione della mappa 1 o 3
|
||||||
@@ -994,7 +944,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
|||||||
if ( MULTITHREAD) {
|
if ( MULTITHREAD) {
|
||||||
|
|
||||||
// Numero massimo di thread
|
// Numero massimo di thread
|
||||||
int nThreadMax = max( 1, int( thread::hardware_concurrency())) ;
|
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||||
vector< future<bool>> vRes ;
|
vector< future<bool>> vRes ;
|
||||||
vRes.resize( nThreadMax) ;
|
vRes.resize( nThreadMax) ;
|
||||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||||
@@ -1006,7 +956,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
|||||||
nInfI = nSupI ;
|
nInfI = nSupI ;
|
||||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM), bForceClosed) ;
|
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1018,7 +968,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
|||||||
nInfJ = nSupJ ;
|
nInfJ = nSupJ ;
|
||||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM), bForceClosed) ;
|
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1037,7 +987,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
|||||||
|
|
||||||
// !!!! NON MULTITHREAD : SOLO PER DEBUG !!!!
|
// !!!! NON MULTITHREAD : SOLO PER DEBUG !!!!
|
||||||
else {
|
else {
|
||||||
CreateMapPart( nG, 0, m_nNx[nG], 0, m_nNy[nG], vtLen, ptMapOrig, Surf, intPLSTM, bForceClosed) ;
|
CreateMapPart( nG, 0, m_nNx[nG], 0, m_nNy[nG], vtLen, ptMapOrig, Surf, intPLSTM) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,583 +1008,3 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
|||||||
|
|
||||||
return bCompleted ;
|
return bCompleted ;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Neigh>
|
|
||||||
VolZmap::GetNeighbours( int nG, int nI, int nJ, double dPar)
|
|
||||||
{
|
|
||||||
vector<Neigh> vNeigh ;
|
|
||||||
// parto da in basso a sinistra e procedo per righe, saltando il punto corrente
|
|
||||||
if ( nI > 0 && nJ > 0)
|
|
||||||
vNeigh.emplace_back( nI - dPar, nJ - dPar, 0) ;
|
|
||||||
if ( nJ > 0) {
|
|
||||||
vNeigh.emplace_back( nI, nJ - dPar, 1) ;
|
|
||||||
if ( nI < m_nNx[nG] - dPar)
|
|
||||||
vNeigh.emplace_back( nI + dPar, nJ - dPar, 2) ;
|
|
||||||
}
|
|
||||||
// passo alla fila contenente il punto corrente
|
|
||||||
if ( nI > 0)
|
|
||||||
vNeigh.emplace_back( nI - dPar, nJ, 3) ;
|
|
||||||
if ( nI < m_nNx[nG] - dPar)
|
|
||||||
vNeigh.emplace_back( nI + dPar, nJ, 5) ;
|
|
||||||
// passo alla fila successiva a quella del corrente
|
|
||||||
if ( nJ < m_nNy[nG] - dPar) {
|
|
||||||
if ( nI > 0)
|
|
||||||
vNeigh.emplace_back( nI - dPar, nJ + dPar, 6) ;
|
|
||||||
vNeigh.emplace_back( nI, nJ + dPar, 7) ;
|
|
||||||
if ( nI < m_nNx[nG] - dPar)
|
|
||||||
vNeigh.emplace_back( nI + dPar, nJ + dPar, 8) ;
|
|
||||||
}
|
|
||||||
return vNeigh ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHECKVEC& vIntToCheck, const Point3d& ptMapOrig,
|
|
||||||
const ISurfTriMesh& Surf, const IntersParLinesSurfTm& intPLSTM)
|
|
||||||
{
|
|
||||||
double dAngSameFace = 45 ;
|
|
||||||
double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ;
|
|
||||||
double dMaxDistTol = 3 * m_dStep ;
|
|
||||||
// per ogni intersezione segnalata devo cercare sugli spilloni vicini l'intervallo con l'estremo più vicino a questa intersezione
|
|
||||||
// e usare l'altro estremo, insieme a quello degli altri spilloni vicini, per estrapolare quello mancante sullo spillone corrente
|
|
||||||
Vector3d vtAx ;
|
|
||||||
if ( nG == 0)
|
|
||||||
vtAx = Z_AX ;
|
|
||||||
else if ( nG == 1)
|
|
||||||
vtAx = X_AX ;
|
|
||||||
else if ( nG == 2)
|
|
||||||
vtAx = Y_AX ;
|
|
||||||
for ( const auto& itc : vIntToCheck) {
|
|
||||||
int nPos = itc.nJ * m_nNx[nG] + itc.nI ;
|
|
||||||
double dPosRef = itc.dU ;
|
|
||||||
bool bUseNeighInfo = true ;
|
|
||||||
// se il punto di intersezione passato non è valido vuol dire che non ho neanche un'intersezione spaiata da cui partire a cercare
|
|
||||||
bool bHaveRef = true ;
|
|
||||||
if ( ! isfinite( dPosRef)) {
|
|
||||||
bHaveRef = false ;
|
|
||||||
bUseNeighInfo = false ;
|
|
||||||
}
|
|
||||||
PNTVECTOR vNeighInters ;
|
|
||||||
Vector3d vtMeanN = V_NULL ;
|
|
||||||
if ( bHaveRef) {
|
|
||||||
// controllo se esiste già un intervallo con un estremo quasi coincidente a quello segnalato
|
|
||||||
// ed entrambi sono entrate o uscite
|
|
||||||
bool bNeedToReconstruct = true ;
|
|
||||||
for ( const auto& data: m_Values[nG][nPos]) {
|
|
||||||
if ( (( abs( dPosRef - data.dMin) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMinN * vtAx) > 0)) ||
|
|
||||||
(( abs( dPosRef - data.dMax) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMaxN * vtAx) > 0))) {
|
|
||||||
bNeedToReconstruct = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ! bNeedToReconstruct)
|
|
||||||
continue ;
|
|
||||||
vector<Neigh> vNeigh = GetNeighbours( nG, itc.nI, itc.nJ, 1) ;
|
|
||||||
bool bSearchingInOrOut = itc.vtN * vtAx > 0 ;
|
|
||||||
for ( const auto& [i, j, n] : vNeigh) {
|
|
||||||
double dMinDist = INFINITO ;
|
|
||||||
double dCorrespInters = INFINITO ;
|
|
||||||
double dNearestPos = NAN ;
|
|
||||||
Vector3d vtNearestN ;
|
|
||||||
int nNeighPos = int( j) * m_nNx[nG] + int( i) ;
|
|
||||||
for ( const auto& data : m_Values[nG][nNeighPos]) {
|
|
||||||
double dDist1 = abs( dPosRef - data.dMin) ;
|
|
||||||
double dDist2 = abs( dPosRef - data.dMax) ;
|
|
||||||
if ( dDist1 < dMinDist || dDist2 < dMinDist) {
|
|
||||||
dMinDist = min( dDist1, dDist2) ;
|
|
||||||
|
|
||||||
// se sto cercando un ingresso
|
|
||||||
if ( bSearchingInOrOut) {
|
|
||||||
if ( data.vtMaxN * vtAx < 0) {
|
|
||||||
dNearestPos = data.dMax ;
|
|
||||||
vtNearestN = data.vtMaxN ;
|
|
||||||
dCorrespInters = data.dMin ;
|
|
||||||
}
|
|
||||||
else if ( data.vtMinN * vtAx < 0) {
|
|
||||||
dNearestPos = data.dMin ;
|
|
||||||
vtNearestN = data.vtMinN ;
|
|
||||||
dCorrespInters = data.dMax ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// se sto cercando un'uscita
|
|
||||||
else {
|
|
||||||
if ( data.vtMaxN * vtAx > 0) {
|
|
||||||
dNearestPos = data.dMax ;
|
|
||||||
vtNearestN = data.vtMaxN ;
|
|
||||||
dCorrespInters = data.dMin ;
|
|
||||||
}
|
|
||||||
else if ( data.vtMinN * vtAx > 0) {
|
|
||||||
dNearestPos = data.dMin ;
|
|
||||||
vtNearestN = data.vtMinN ;
|
|
||||||
dCorrespInters = data.dMax ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// verifico che il dNearestPos sia effettivamente associato al tratto che sto cercando di ricostruire
|
|
||||||
// e non ad un altro presente sullo spillone corrente
|
|
||||||
bool bAddNearest = true ;
|
|
||||||
for ( const auto& data : m_Values[nG][nPos]) {
|
|
||||||
double dDist1 = abs( dCorrespInters - data.dMin) ;
|
|
||||||
double dDist2 = abs( dCorrespInters - data.dMax) ;
|
|
||||||
if ( dDist1 < dMinDist || dDist2 < dMinDist) {
|
|
||||||
bAddNearest = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bAddNearest && isfinite( dNearestPos)) {
|
|
||||||
// controllo anche che i punti non siano troppo lontani tra loro, altrimenti
|
|
||||||
// il piano calcolato potrebbe essere una media troppo grezza
|
|
||||||
const bool bTooFar = any_of( vNeighInters.begin(), vNeighInters.end(),
|
|
||||||
[dNearestPos, dMaxDistTol](const Point3d& pt) {
|
|
||||||
return abs( pt.z - dNearestPos) > dMaxDistTol ;
|
|
||||||
}) ;
|
|
||||||
double dAng ;
|
|
||||||
if ( ! bTooFar) {
|
|
||||||
// controllo anche che gli angoli delle normali non cambino troppo
|
|
||||||
// calcolo l'angolo con la media delle precedenti perché il valore oltre cui
|
|
||||||
// considero le normali diverse è grande
|
|
||||||
vtNearestN.GetAngle( vtMeanN, dAng) ;
|
|
||||||
}
|
|
||||||
bAddNearest = ! bTooFar && dAng < dAngSameFace ;
|
|
||||||
if ( bAddNearest) {
|
|
||||||
double dX = ( i + 0.5) * m_dStep ;
|
|
||||||
double dY = ( j + 0.5) * m_dStep ;
|
|
||||||
vNeighInters.emplace_back( dX, dY, dNearestPos) ;
|
|
||||||
vtMeanN += vtNearestN ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bUseNeighInfo = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vector<Data> vNewIntervals ;
|
|
||||||
bool bAddAllIntervals = false ;
|
|
||||||
Point3d ptInt ;
|
|
||||||
// se riesco uso i vicini per calcolare l'intersezione mancante
|
|
||||||
if ( bUseNeighInfo) {
|
|
||||||
// se non ci sono almeno tre punti, non allineati, non riesco a determinare il piano con cui tagliare lo spillone
|
|
||||||
if ( ssize( vNeighInters) < 3)
|
|
||||||
continue ;
|
|
||||||
else if ( ssize( vNeighInters) == 3){
|
|
||||||
// verifico che non siano allineati
|
|
||||||
if ( ( vNeighInters[0].x == vNeighInters[1].x && vNeighInters[0].x == vNeighInters[1].x) ||
|
|
||||||
( vNeighInters[0].y == vNeighInters[1].y && vNeighInters[0].y == vNeighInters[1].y))
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
// se sono più di tre sicuramente non sono allieanti, visto che sono intorno allo spillone corrente
|
|
||||||
vtMeanN.Normalize() ;
|
|
||||||
Plane3d plLoc ;
|
|
||||||
PolyLine PL ; PL.FromPointVector( vNeighInters) ;
|
|
||||||
PL.IsFlat( plLoc, INFINITO) ;
|
|
||||||
|
|
||||||
// porto anche il punto dell'intersezione nel frame della griglia
|
|
||||||
Point3d ptKnown = itc.ptInters ;
|
|
||||||
Frame3d frGrid ;
|
|
||||||
if ( nG == 0)
|
|
||||||
frGrid.Set( ptMapOrig, Frame3d::TOP) ;
|
|
||||||
else if ( nG == 1)
|
|
||||||
frGrid.Set( ptMapOrig, Frame3d::RIGHT) ;
|
|
||||||
else if ( nG == 2)
|
|
||||||
frGrid.Set( ptMapOrig, Z_AX, X_AX, Y_AX) ;
|
|
||||||
ptKnown.ToLoc( frGrid) ;
|
|
||||||
IntersLinePlane( ptKnown, Z_AX, INFINITO, plLoc, ptInt, false) ;
|
|
||||||
}
|
|
||||||
// altrimenti sposto di poco lo spillone e ricalcolo le intersezioni con la superficie, finché trovo l'intersezione mancante
|
|
||||||
else {
|
|
||||||
// controllo quanti intervalli hanno i vicini
|
|
||||||
vector<Neigh> vNeigh = GetNeighbours( nG, itc.nI, itc.nJ, 1) ;
|
|
||||||
int nMinIntervals = 0 ;
|
|
||||||
for ( const auto& [i, j, n] : vNeigh) {
|
|
||||||
int nNeighPos = int( j) * m_nNx[nG] + int( i) ;
|
|
||||||
if ( ssize(m_Values[nG][nNeighPos]) > nMinIntervals)
|
|
||||||
nMinIntervals = ssize(m_Values[nG][nNeighPos]) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bFound = false ;
|
|
||||||
DBLVECTOR vSmallStep ;
|
|
||||||
vSmallStep.push_back( Clamp( 0.05 * m_dStep, 50 * EPS_SMALL, 1.)) ;
|
|
||||||
vSmallStep.push_back( Clamp( 0.2 * m_dStep, 50 * EPS_SMALL, 1.)) ;
|
|
||||||
// ciclo una raggiera di spilloni ( a distanza inferiore allo m_dStep) attorno allo spillone
|
|
||||||
// appena trova un'intersezione buona mi fermo
|
|
||||||
// se ciclando la raggiera non trovo un'intersezione valida allora potrei essermi spostato troppo poco dallo spillone originale e essere caduto ancora nella fessura
|
|
||||||
// quindi ciclo nuovamente aumentando un poco la distanza dallo spillone originale ( comunque sempre meno della distanza m_dStep)
|
|
||||||
for ( int c = 0 ; c < ssize( vSmallStep) ; ++c) {
|
|
||||||
vector<Neigh> vSmallMoveNeigh = GetNeighbours( nG, itc.nI, itc.nJ, vSmallStep[c]) ;
|
|
||||||
for ( int n = 0 ; n < ssize( vSmallMoveNeigh) ; ++n) {
|
|
||||||
double dX = ( vSmallMoveNeigh[n].nI + 0.5) * m_dStep ;
|
|
||||||
double dY = ( vSmallMoveNeigh[n].nJ + 0.5) * m_dStep ;
|
|
||||||
Point3d ptP0( dX, dY, 0) ;
|
|
||||||
ILSIVECTOR IntersectionResults ;
|
|
||||||
intPLSTM.GetInters( ptP0, vtLen.v[(nG+2)%3], IntersectionResults) ;
|
|
||||||
// intervalli dalle intersezioni
|
|
||||||
vNewIntervals.clear() ;
|
|
||||||
DBLVECTOR vDiscardedInters ;
|
|
||||||
bool bInside = false ;
|
|
||||||
Vector3d vtInN ;
|
|
||||||
Point3d ptIn ;
|
|
||||||
for ( int i = 0 ; i < ssize( IntersectionResults) ; ++i) {
|
|
||||||
// Se c'è intersezione
|
|
||||||
if ( IntersectionResults[i].nILTT != ILTT_NO) {
|
|
||||||
if ( i > 0) {
|
|
||||||
int z = i - 1 ;
|
|
||||||
// controllo se l'intersezione corrente è coincidente con la precedente, per esempio se ILTT == 4 ( intersezione su un lato di un triangolo, quindi con 2 triangoli)
|
|
||||||
if ( IntersectionResults[i].dU - IntersectionResults[z].dU < EPS_SMALL &&
|
|
||||||
IntersectionResults[i].dCosDN - IntersectionResults[z].dCosDN < EPS_SMALL)
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
double dCos = IntersectionResults[i].dCosDN ;
|
|
||||||
// entro nella superficie trimesh
|
|
||||||
if ( dCos < - dCosSmall) {
|
|
||||||
if ( bInside) {
|
|
||||||
int k = i - 1 ;
|
|
||||||
vDiscardedInters.push_back( IntersectionResults[k].dU) ;
|
|
||||||
}
|
|
||||||
ptIn = IntersectionResults[i].ptI ;
|
|
||||||
|
|
||||||
int nT = IntersectionResults[i].nT ;
|
|
||||||
int nF = Surf.GetFacetFromTria( nT) ;
|
|
||||||
|
|
||||||
Surf.GetFacetNormal( nF, vtInN) ;
|
|
||||||
|
|
||||||
bInside = true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// esco dalla superficie trimesh
|
|
||||||
else if ( dCos > dCosSmall) {
|
|
||||||
if ( ! bInside) {
|
|
||||||
vDiscardedInters.push_back( IntersectionResults[i].dU) ;
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
Point3d ptOut = IntersectionResults[i].ptI ;
|
|
||||||
|
|
||||||
int nT = IntersectionResults[i].nT ;
|
|
||||||
int nF = Surf.GetFacetFromTria( nT) ;
|
|
||||||
|
|
||||||
Vector3d vtOutN ;
|
|
||||||
Surf.GetFacetNormal( nF, vtOutN) ;
|
|
||||||
|
|
||||||
// Aggiungo un tratto al dexel
|
|
||||||
vNewIntervals.emplace_back() ;
|
|
||||||
|
|
||||||
// Aggiorno dati del tratto di dexel
|
|
||||||
vNewIntervals.back().dMin = ptIn.v[(nG+2)%3] - ptMapOrig.v[(nG+2)%3] ;
|
|
||||||
vNewIntervals.back().dMax = ptOut.v[(nG+2)%3] - ptMapOrig.v[(nG+2)%3] ;
|
|
||||||
vNewIntervals.back().vtMinN = vtInN ;
|
|
||||||
vNewIntervals.back().vtMaxN = vtOutN ;
|
|
||||||
vNewIntervals.back().nToolMin = 0 ;
|
|
||||||
vNewIntervals.back().nToolMax = 0 ;
|
|
||||||
vNewIntervals.back().nCompo = 0 ;
|
|
||||||
|
|
||||||
bInside = false ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//// controllo che abbia almeno un intervallo in più rispetto a quelli di prima
|
|
||||||
//bool bValidNewIntrerval = ssize( vNewIntervals) > ssize( m_Values[nG][nPos]) ;
|
|
||||||
//if ( ! bHaveRef)
|
|
||||||
// bValidNewIntrerval = bValidNewIntrerval && ssize( vNewIntervals) >= nMinIntervals ;
|
|
||||||
|
|
||||||
//// controllo che ci sia almeno un intervallo che non matcha con quelli già presenti
|
|
||||||
//bool bValidNewIntrerval = false ;
|
|
||||||
//if ( ssize( m_Values[nG][nPos]) == 0)
|
|
||||||
// bValidNewIntrerval = true ;
|
|
||||||
//else {
|
|
||||||
// for ( auto& dataCurr : m_Values[nG][nPos]) {
|
|
||||||
// // se ho una sovrapposizione tra intervalli ho una corrispondenza
|
|
||||||
// bool bMatch = false ;
|
|
||||||
// for ( auto& dataNew : vNewIntervals) {
|
|
||||||
// if ( dataCurr.dMin < dataNew.dMax && dataNew.dMin < dataCurr.dMax) {
|
|
||||||
// bMatch = true ;
|
|
||||||
// break ;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ( ! bMatch) {
|
|
||||||
// bValidNewIntrerval = true ;
|
|
||||||
// break ;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool bValidNewInterval = false ;
|
|
||||||
// cerco se ho delle corrispondenza tra gli intervalli che avevo già sul corrente
|
|
||||||
// e quelli che ho trovato ora
|
|
||||||
bool bSplit = false ;
|
|
||||||
INTINTVECTOR vMatch ;
|
|
||||||
int nNew = 0 ;
|
|
||||||
for ( auto& dataNew : vNewIntervals) {
|
|
||||||
// se ho una sovrapposizione tra intervalli ho una corrispondenza
|
|
||||||
int nCurr = 0 ;
|
|
||||||
bool bMatch = false ;
|
|
||||||
for ( auto& dataCurr : m_Values[nG][nPos]) {
|
|
||||||
if ( dataCurr.dMin < dataNew.dMax && dataNew.dMin < dataCurr.dMax) {
|
|
||||||
if ( ! vMatch.empty() && nCurr == vMatch.back().first)
|
|
||||||
bSplit = true ;
|
|
||||||
vMatch.emplace_back( nCurr, nNew) ;
|
|
||||||
bMatch = true ;
|
|
||||||
}
|
|
||||||
++nCurr ;
|
|
||||||
}
|
|
||||||
if ( ! bMatch && ssize( vNewIntervals) > 0)
|
|
||||||
bValidNewInterval = true ;
|
|
||||||
++ nNew ;
|
|
||||||
}
|
|
||||||
bool bEnoughIntervals = bHaveRef ? ssize( vNewIntervals) > 0 : ssize( vNewIntervals) >= nMinIntervals ;
|
|
||||||
if ( ssize( m_Values[nG][nPos]) == 0 && bEnoughIntervals)
|
|
||||||
bValidNewInterval = true ;
|
|
||||||
// se ho trovato almeno un intervallo senza corrispondenza devo aggiungerlo
|
|
||||||
// se ho trovato un intervallo sul corrente che matcha due intervalli nuovi allora devo spezzare quello sul corrente
|
|
||||||
if ( bValidNewInterval || bSplit) {
|
|
||||||
// se avevo un punto disaccoppiato lo uso come riferimento
|
|
||||||
if ( bHaveRef) {
|
|
||||||
// devo controllare se l'intervallo in più è quello che cercavo
|
|
||||||
// controllo anche tra le intersezioni scartate
|
|
||||||
double dMinDist = INFINITO ;
|
|
||||||
for ( const auto& data : vNewIntervals) {
|
|
||||||
if ( abs( data.dMin - dPosRef) < dMinDist) {
|
|
||||||
dMinDist = abs( data.dMin - dPosRef) ;
|
|
||||||
ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMax) ;
|
|
||||||
vtMeanN = data.vtMaxN ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
if ( abs( data.dMax - dPosRef) < dMinDist) {
|
|
||||||
dMinDist = abs( data.dMax - dPosRef) ;
|
|
||||||
ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMin) ;
|
|
||||||
vtMeanN = data.vtMinN ;
|
|
||||||
bFound = true ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( const auto& dU : vDiscardedInters) {
|
|
||||||
if ( abs( dU - dPosRef) < dMinDist) {
|
|
||||||
bFound = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bFound = true ;
|
|
||||||
if ( ssize( m_Values[nG][nPos]) == 0 || ! bSplit) {
|
|
||||||
// se non avevo intervalli sul corrente tengo tutto quello trovo
|
|
||||||
bAddAllIntervals = true ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// altrimenti mi aspetto di aver attraversato due fessure e quindi di avere sullo spillone corrente un
|
|
||||||
// intervallo il cui inizio e fine corrispondono a inizio di un intervallo e fine del successivo
|
|
||||||
INTVECTOR vErase ;
|
|
||||||
for ( int z = 1 ; z < ssize( vMatch) ; ++z) {
|
|
||||||
if ( vMatch[z].first == vMatch[z-1].first) {
|
|
||||||
vErase.push_back( vMatch[z].first) ;
|
|
||||||
Data& data = vNewIntervals[vMatch[z-1].second] ;
|
|
||||||
Data& dataNext = vNewIntervals[vMatch[z].second] ;
|
|
||||||
m_Values[nG][nPos].emplace_back() ;
|
|
||||||
m_Values[nG][nPos].emplace_back() ;
|
|
||||||
Data& dataCurr = m_Values[nG][nPos][vMatch[z].first] ;
|
|
||||||
// primo
|
|
||||||
m_Values[nG][nPos].end()[-2].dMin = dataCurr.dMin;
|
|
||||||
m_Values[nG][nPos].end()[-2].dMax = data.dMax ;
|
|
||||||
m_Values[nG][nPos].end()[-2].vtMinN = dataCurr.vtMinN ;
|
|
||||||
m_Values[nG][nPos].end()[-2].vtMaxN = data.vtMaxN ;
|
|
||||||
m_Values[nG][nPos].end()[-2].nToolMin = 0 ;
|
|
||||||
m_Values[nG][nPos].end()[-2].nToolMax = 0 ;
|
|
||||||
m_Values[nG][nPos].end()[-2].nCompo = 0 ;
|
|
||||||
// secondo
|
|
||||||
m_Values[nG][nPos].end()[-1].dMin = dataNext.dMin;
|
|
||||||
m_Values[nG][nPos].end()[-1].dMax = dataCurr.dMax ;
|
|
||||||
m_Values[nG][nPos].end()[-1].vtMinN = dataNext.vtMinN ;
|
|
||||||
m_Values[nG][nPos].end()[-1].vtMaxN = dataCurr.vtMaxN ;
|
|
||||||
m_Values[nG][nPos].end()[-1].nToolMin = 0 ;
|
|
||||||
m_Values[nG][nPos].end()[-1].nToolMax = 0 ;
|
|
||||||
m_Values[nG][nPos].end()[-1].nCompo = 0 ;
|
|
||||||
++z ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// cancello gli intervalli che sono stati splittati
|
|
||||||
for ( int z : views::reverse( vErase))
|
|
||||||
m_Values[nG][nPos].erase( m_Values[nG][nPos].begin() + z) ;
|
|
||||||
}
|
|
||||||
// cancello gli intervalli per cui avevo già un corrispettivo sul corrente, a meno che non sia una doppia corrispondenza
|
|
||||||
// in quel caso devo spezzare l'intervallo sul corrente
|
|
||||||
// prima elimino i doppioni da vMatch
|
|
||||||
for ( int z = ssize( vMatch) - 1 ; z > 0; --z) {
|
|
||||||
if ( vMatch[z].second == vMatch[z-1].second)
|
|
||||||
vMatch.erase( vMatch.begin() + z) ;
|
|
||||||
}
|
|
||||||
for ( auto [ nCurr, nNew] : views::reverse( vMatch))
|
|
||||||
vNewIntervals.erase( vNewIntervals.begin() + nNew) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bFound)
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
if ( bFound)
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
// se cercando nei dintorni dello spillone non ho trovato l'intersezione mancante, mi arrendo
|
|
||||||
if ( ! bFound)
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( ! bAddAllIntervals && bHaveRef) {
|
|
||||||
double dMin, dMax ;
|
|
||||||
Vector3d vtMinN, vtMaxN ;
|
|
||||||
if ( itc.dU < ptInt.z) {
|
|
||||||
dMin = itc.dU ;
|
|
||||||
dMax = ptInt.z ;
|
|
||||||
vtMinN = itc.vtN ;
|
|
||||||
vtMaxN = vtMeanN ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dMin = ptInt.z ;
|
|
||||||
dMax = itc.dU ;
|
|
||||||
vtMinN = vtMeanN ;
|
|
||||||
vtMaxN = itc.vtN ;
|
|
||||||
}
|
|
||||||
// prima di aggiungere il tratto verifico che non si sovrapponga con un tratto già presente
|
|
||||||
bool bAdd = true ;
|
|
||||||
for ( const auto& data: m_Values[nG][nPos]) {
|
|
||||||
if ( dMin < data.dMax && data.dMin < dMax) {
|
|
||||||
bAdd = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bAdd) {
|
|
||||||
m_Values[nG][nPos].emplace_back() ;
|
|
||||||
m_Values[nG][nPos].back().dMin = dMin;
|
|
||||||
m_Values[nG][nPos].back().dMax = dMax ;
|
|
||||||
m_Values[nG][nPos].back().vtMinN = vtMinN ;
|
|
||||||
m_Values[nG][nPos].back().vtMaxN = vtMaxN ;
|
|
||||||
m_Values[nG][nPos].back().nToolMin = 0 ;
|
|
||||||
m_Values[nG][nPos].back().nToolMax = 0 ;
|
|
||||||
m_Values[nG][nPos].back().nCompo = 0 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for ( const auto& dataNew: vNewIntervals) {
|
|
||||||
// prima di aggiungere il tratto verifico che non si sovrapponga con un tratto già presente
|
|
||||||
bool bAdd = true ;
|
|
||||||
for ( const auto& data: m_Values[nG][nPos]) {
|
|
||||||
if ( dataNew.dMin < data.dMax && data.dMin < dataNew.dMax) {
|
|
||||||
bAdd = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bAdd) {
|
|
||||||
m_Values[nG][nPos].emplace_back() ;
|
|
||||||
m_Values[nG][nPos].back().dMin = dataNew.dMin;
|
|
||||||
m_Values[nG][nPos].back().dMax = dataNew.dMax ;
|
|
||||||
m_Values[nG][nPos].back().vtMinN = dataNew.vtMinN ;
|
|
||||||
m_Values[nG][nPos].back().vtMaxN = dataNew.vtMaxN ;
|
|
||||||
m_Values[nG][nPos].back().nToolMin = 0 ;
|
|
||||||
m_Values[nG][nPos].back().nToolMax = 0 ;
|
|
||||||
m_Values[nG][nPos].back().nCompo = 0 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort( m_Values[nG][nPos].begin(), m_Values[nG][nPos].end(), []( Data& a, Data& b) { return a.dMin < b.dMin ;}) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ad ogni lato assegno un bit
|
|
||||||
enum NeighSide {
|
|
||||||
BOTTOM = 1 << 0,
|
|
||||||
RIGHT = 1 << 1,
|
|
||||||
TOP = 1 << 2,
|
|
||||||
LEFT = 1 << 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// con una mask verifico se due punti stanno sullo stesso lato
|
|
||||||
bool AreOnSameEdge( int a, int b)
|
|
||||||
{
|
|
||||||
static const int mask[9] = {
|
|
||||||
BOTTOM | LEFT, // 0
|
|
||||||
BOTTOM, // 1
|
|
||||||
BOTTOM | RIGHT, // 2
|
|
||||||
LEFT, // 3
|
|
||||||
0, // 4 (centro)
|
|
||||||
RIGHT, // 5
|
|
||||||
TOP | LEFT, // 6
|
|
||||||
TOP, // 7
|
|
||||||
TOP | RIGHT // 8
|
|
||||||
};
|
|
||||||
|
|
||||||
return ( mask[a] & mask[b]) != 0 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr int position[9] =
|
|
||||||
{
|
|
||||||
0, // 0
|
|
||||||
1, // 1
|
|
||||||
2, // 2
|
|
||||||
7, // 3
|
|
||||||
-1, // 4 (centro)
|
|
||||||
3, // 5
|
|
||||||
6, // 6
|
|
||||||
5, // 7
|
|
||||||
4 // 8
|
|
||||||
} ;
|
|
||||||
|
|
||||||
bool AreOpposite( int a, int b)
|
|
||||||
{
|
|
||||||
// a partire da un punto cosidero suoi opposti l'opposto geometrico e i suoi vicini
|
|
||||||
// quindi i punti a distanza 3,4,5 salti dal punto di partenza
|
|
||||||
int pa = position[a] ;
|
|
||||||
int pb = position[b] ;
|
|
||||||
|
|
||||||
if ( pa == -1 || pb == -1)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
int d = ( pb - pa + 8) % 8 ;
|
|
||||||
|
|
||||||
return d == 3 || d == 4 || d == 5 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AreOpposite2( int a, int b)
|
|
||||||
{
|
|
||||||
return a + b == 8 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
VolZmap::SearchMissingIntervals( int nMap, INTTOCHECKVEC& vIntToCheck)
|
|
||||||
{
|
|
||||||
|
|
||||||
for ( int nI = 0 ; nI < m_nNx[nMap] ; ++nI) {
|
|
||||||
for ( int nJ = 0 ; nJ < m_nNy[nMap] ; ++nJ) {
|
|
||||||
int nPos = int( nJ) * m_nNx[nMap] + int( nI) ;
|
|
||||||
vector<Neigh> vNeigh = GetNeighbours( nMap, nI, nJ, 1) ;
|
|
||||||
if ( ssize( m_Values[nMap][nPos]) > 0) {
|
|
||||||
// se tra i vicini ne trovo uno con lo stesso numero di intervalli allora il corrente è a posto
|
|
||||||
// sennò devo analizzarlo
|
|
||||||
bool bFoundAlike = false ;
|
|
||||||
for ( const auto& [i,j,n] : vNeigh) {
|
|
||||||
int nNeighPos = int( j) * m_nNx[nMap] + int( i) ;
|
|
||||||
if ( ssize( m_Values[nMap][nNeighPos]) == ssize( m_Values[nMap][nPos])) {
|
|
||||||
bFoundAlike = true ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ! bFoundAlike)
|
|
||||||
vIntToCheck.emplace_back( P_INVALID, V_INVALID, double( NAN), nMap, nI, nJ) ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
INTVECTOR nNeighTrig ;
|
|
||||||
for ( const auto& [i,j,n] : vNeigh) {
|
|
||||||
int nNeighPos = int( j) * m_nNx[nMap] + int( i) ;
|
|
||||||
if ( ssize( m_Values[nMap][nNeighPos]) > ssize( m_Values[nMap][nPos])) {
|
|
||||||
nNeighTrig.push_back( n) ;
|
|
||||||
if ( ! nNeighTrig.empty() && any_of( nNeighTrig.begin(), nNeighTrig.end(), [n]( int nNeigh) { return AreOpposite2( nNeigh, n) ;})) {
|
|
||||||
vIntToCheck.emplace_back( P_INVALID, V_INVALID, double( NAN), nMap, nI, nJ) ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
+2
-2
@@ -36,7 +36,7 @@ using namespace std ;
|
|||||||
static const int MAX_FAN_BASE_VERTS = 7 ;
|
static const int MAX_FAN_BASE_VERTS = 7 ;
|
||||||
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor, MAX_FAN_BASE_VERTS, 3> SvdMatrix ;
|
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor, MAX_FAN_BASE_VERTS, 3> SvdMatrix ;
|
||||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::ColMajor, MAX_FAN_BASE_VERTS, 1> SvdVector ;
|
typedef Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::ColMajor, MAX_FAN_BASE_VERTS, 1> SvdVector ;
|
||||||
typedef Eigen::JacobiSVD<SvdMatrix, Eigen::ComputeThinU | Eigen::ComputeThinV> SvdDecomposer ;
|
typedef Eigen::JacobiSVD<SvdMatrix, Eigen::QRPreconditioners::ColPivHouseholderQRPreconditioner> SvdDecomposer ;
|
||||||
|
|
||||||
// ------------------------- FUNZIONE TEST SULLE NORMALI --------------------------------------------------------------------------
|
// ------------------------- FUNZIONE TEST SULLE NORMALI --------------------------------------------------------------------------
|
||||||
enum FatureType { NO_FEATURE = 0, CORNER = 1, EDGE = 2} ;
|
enum FatureType { NO_FEATURE = 0, CORNER = 1, EDGE = 2} ;
|
||||||
@@ -2036,7 +2036,7 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calcolo SVD
|
// calcolo SVD
|
||||||
SvdDecomposer svd( dMatrixN) ;
|
SvdDecomposer svd( dMatrixN, Eigen::ComputeThinU | Eigen::ComputeThinV) ;
|
||||||
const auto& dSingularValue = svd.singularValues() ;
|
const auto& dSingularValue = svd.singularValues() ;
|
||||||
const auto& dMatrixV = svd.matrixV() ;
|
const auto& dMatrixV = svd.matrixV() ;
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -21,7 +21,6 @@
|
|||||||
#include "CurveLine.h"
|
#include "CurveLine.h"
|
||||||
#include "CurveArc.h"
|
#include "CurveArc.h"
|
||||||
#include "GeoConst.h"
|
#include "GeoConst.h"
|
||||||
#include "IntersLineCyl.h"
|
|
||||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||||
@@ -734,7 +733,7 @@ VolZmap::AddSurfTmForOffset( const ISurfTriMesh* pStm, int nTool)
|
|||||||
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
||||||
|
|
||||||
// numero massimo di thread
|
// numero massimo di thread
|
||||||
int nThreadMax = max( 1, int( thread::hardware_concurrency())) ;
|
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||||
vector<future<bool>> vRes ;
|
vector<future<bool>> vRes ;
|
||||||
vRes.resize( nThreadMax) ;
|
vRes.resize( nThreadMax) ;
|
||||||
// se dimensione griglia in X maggiore di dimensione Y
|
// se dimensione griglia in X maggiore di dimensione Y
|
||||||
@@ -969,13 +968,12 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d
|
|||||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||||
Point3d ptInt1, ptInt2 ;
|
Point3d ptInt1, ptInt2 ;
|
||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
double dU1, dU2 ;
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
|
||||||
if ( dOffs > 0.)
|
if ( dOffs > 0.)
|
||||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool, nTool) ;
|
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ;
|
||||||
else
|
else
|
||||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
|
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-31
@@ -21,7 +21,6 @@
|
|||||||
#include "VolZmap.h"
|
#include "VolZmap.h"
|
||||||
#include "GeoConst.h"
|
#include "GeoConst.h"
|
||||||
#include "IntersLineBox.h"
|
#include "IntersLineBox.h"
|
||||||
#include "IntersLineCyl.h"
|
|
||||||
#include "/EgtDev/Include/EGkIntervals.h"
|
#include "/EgtDev/Include/EGkIntervals.h"
|
||||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||||
@@ -2610,15 +2609,7 @@ VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, co
|
|||||||
|
|
||||||
// Calcolo angoli di rotazione utensile longitudinale e trasversale rispetto al movimento per eventuale suddivisione
|
// Calcolo angoli di rotazione utensile longitudinale e trasversale rispetto al movimento per eventuale suddivisione
|
||||||
double dAlongAngDeg, dAcrossAngDeg ;
|
double dAlongAngDeg, dAcrossAngDeg ;
|
||||||
if ( m_vTool[m_nCurrTool].GetRadius() < 40)
|
GetAlongAcrossRotation( vtDs, vtDe, ptPe - ptPs, dAlongAngDeg, dAcrossAngDeg) ;
|
||||||
GetAlongAcrossRotation( vtDs, vtDe, ptPe - ptPs, dAlongAngDeg, dAcrossAngDeg) ;
|
|
||||||
else {
|
|
||||||
// se è una lama uso un asse diverso per calcolare le rotaziona del vettore tool
|
|
||||||
Vector3d vtAxis = vtDs ^ vtDe ;
|
|
||||||
GetAlongAcrossRotation( vtDs, vtDe, vtAxis, dAlongAngDeg, dAcrossAngDeg) ;
|
|
||||||
swap( dAlongAngDeg, dAcrossAngDeg) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Calcolo numero degli step di movimento
|
// Calcolo numero degli step di movimento
|
||||||
int nStepCnt = int( max( { abs( dAlongAngDeg) / ANG_ALONG_STEP, abs( dAcrossAngDeg) / ANG_ACROSS_STEP, 1.})) ;
|
int nStepCnt = int( max( { abs( dAlongAngDeg) / ANG_ALONG_STEP, abs( dAcrossAngDeg) / ANG_ACROSS_STEP, 1.})) ;
|
||||||
@@ -2727,7 +2718,7 @@ VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, co
|
|||||||
InitializePointsAndVectors( ptSti, ptEni, vtDSi, vtDEi, ptLs, ptLe, vtLs, vtLe) ;
|
InitializePointsAndVectors( ptSti, ptEni, vtDSi, vtDEi, ptLs, ptLe, vtLs, vtLe) ;
|
||||||
|
|
||||||
// Standard è multithread
|
// Standard è multithread
|
||||||
constexpr bool MULTITHREAD = true ;
|
constexpr bool MULTITHREAD = false ;
|
||||||
if ( MULTITHREAD) {
|
if ( MULTITHREAD) {
|
||||||
// Ciclo sulle mappe
|
// Ciclo sulle mappe
|
||||||
vector<future<bool>> vRes( m_nMapNum) ;
|
vector<future<bool>> vRes( m_nMapNum) ;
|
||||||
@@ -6258,8 +6249,7 @@ VolZmap::CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, co
|
|||||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||||
Point3d ptInt1, ptInt2 ;
|
Point3d ptInt1, ptInt2 ;
|
||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
double dU1, dU2 ;
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
|
||||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6304,9 +6294,8 @@ VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
|
|
||||||
// Cilindro
|
// Cilindro
|
||||||
double dU1, dU2 ;
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
|
||||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6485,8 +6474,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|||||||
|
|
||||||
// Cilindro iniziale
|
// Cilindro iniziale
|
||||||
CylFrame.ChangeOrig( ptITip) ;
|
CylFrame.ChangeOrig( ptITip) ;
|
||||||
double dU1, dU2 ;
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
|
||||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6494,7 +6482,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|||||||
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
|
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
|
||||||
// il vettore che congiunge le due origini.
|
// il vettore che congiunge le due origini.
|
||||||
CylFrame.ChangeOrig( ptITip + vtMove) ;
|
CylFrame.ChangeOrig( ptITip + vtMove) ;
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7081,8 +7069,7 @@ VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe,
|
|||||||
// Cilindro inviluppo della sfera
|
// Cilindro inviluppo della sfera
|
||||||
Point3d ptInt1, ptInt2 ;
|
Point3d ptInt1, ptInt2 ;
|
||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
double dU1, dU2 ;
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
|
||||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7230,15 +7217,15 @@ VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, cons
|
|||||||
|
|
||||||
Point3d ptInt1, ptInt2 ;
|
Point3d ptInt1, ptInt2 ;
|
||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
double dU1, dU2 ;
|
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( IntersLineCyl( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
|
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
|
||||||
@@ -7634,9 +7621,8 @@ VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double
|
|||||||
// Cilindro inviluppo della sfera
|
// Cilindro inviluppo della sfera
|
||||||
Point3d ptInt1, ptInt2 ;
|
Point3d ptInt1, ptInt2 ;
|
||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
double dU1, dU2 ;
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-81
@@ -434,7 +434,6 @@ Voronoi::GetBisectorCurve( int i)
|
|||||||
pLine->Set( ptS, ptE) ;
|
pLine->Set( ptS, ptE) ;
|
||||||
pLine->SetTempParam( dParS, 0) ;
|
pLine->SetTempParam( dParS, 0) ;
|
||||||
pLine->SetTempParam( dParE, 1) ;
|
pLine->SetTempParam( dParE, 1) ;
|
||||||
pLine->SetTempProp( i) ;
|
|
||||||
pLine->ToGlob( m_Frame) ;
|
pLine->ToGlob( m_Frame) ;
|
||||||
return pLine ;
|
return pLine ;
|
||||||
}
|
}
|
||||||
@@ -455,7 +454,6 @@ Voronoi::GetBisectorCurve( int i)
|
|||||||
pArc->SetC2P( ptC, ptS, ptE) ;
|
pArc->SetC2P( ptC, ptS, ptE) ;
|
||||||
pArc->SetTempParam( dParS, 0) ;
|
pArc->SetTempParam( dParS, 0) ;
|
||||||
pArc->SetTempParam( dParS, 1) ; // dParE = dParS
|
pArc->SetTempParam( dParS, 1) ; // dParE = dParS
|
||||||
pArc->SetTempProp( i) ;
|
|
||||||
pArc->ToGlob( m_Frame) ;
|
pArc->ToGlob( m_Frame) ;
|
||||||
return pArc ;
|
return pArc ;
|
||||||
}
|
}
|
||||||
@@ -475,7 +473,7 @@ Voronoi::GetBisectorCurve( int i)
|
|||||||
bool bInvert = false ;
|
bool bInvert = false ;
|
||||||
double dPar1, dPar2 ;
|
double dPar1, dPar2 ;
|
||||||
m_vroni->GetApproxedBisectorParams( i, dPar1, dPar2) ;
|
m_vroni->GetApproxedBisectorParams( i, dPar1, dPar2) ;
|
||||||
if ( dPar1 > dPar2)
|
if ( dPar1 > dPar2 + EPS_SMALL)
|
||||||
bInvert = true ;
|
bInvert = true ;
|
||||||
|
|
||||||
// punto iniziale
|
// punto iniziale
|
||||||
@@ -498,11 +496,6 @@ Voronoi::GetBisectorCurve( int i)
|
|||||||
dParPrev = dPar ;
|
dParPrev = dPar ;
|
||||||
nCrvCount ++ ;
|
nCrvCount ++ ;
|
||||||
}
|
}
|
||||||
else if ( ( bInvert && j == 0) || ( ! bInvert && j == nPoints - 1)) {
|
|
||||||
// se estremo devo forzarlo
|
|
||||||
pCompo->ModifyEnd( pt) ;
|
|
||||||
dParPrev = dPar ;
|
|
||||||
}
|
|
||||||
// aggiorno per punto successivo
|
// aggiorno per punto successivo
|
||||||
if ( bInvert)
|
if ( bInvert)
|
||||||
j -- ;
|
j -- ;
|
||||||
@@ -513,7 +506,6 @@ Voronoi::GetBisectorCurve( int i)
|
|||||||
// setto parametri sulla curva
|
// setto parametri sulla curva
|
||||||
pCompo->SetTempParam( dParS, 0) ;
|
pCompo->SetTempParam( dParS, 0) ;
|
||||||
pCompo->SetTempParam( dParPrev, 1) ;
|
pCompo->SetTempParam( dParPrev, 1) ;
|
||||||
pCompo->SetTempProp( i) ;
|
|
||||||
|
|
||||||
pCompo->ToGlob( m_Frame) ;
|
pCompo->ToGlob( m_Frame) ;
|
||||||
return pCompo ;
|
return pCompo ;
|
||||||
@@ -708,8 +700,8 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
|||||||
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
|
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
|
||||||
if ( bLeft && bRight) {
|
if ( bLeft && bRight) {
|
||||||
// recupero i siti di riferimento
|
// recupero i siti di riferimento
|
||||||
int nOrigCrv1, nOrigSubCrv1, nOrigSubPnt1, nOrigCrv2, nOrigSubCrv2, nOrigSubPnt2 ;
|
int nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2 ;
|
||||||
m_vroni->GetBisectorSites( i, nOrigCrv1, nOrigSubCrv1, nOrigSubPnt1, nOrigCrv2, nOrigSubCrv2, nOrigSubPnt2) ;
|
m_vroni->GetBisectorSites( i, nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2) ;
|
||||||
if ( nOrigCrv1 != -1) {
|
if ( nOrigCrv1 != -1) {
|
||||||
// verifico il lato rispetto al primo sito
|
// verifico il lato rispetto al primo sito
|
||||||
pCrv->SetTempProp( nOrigSubCrv1 + 1, 0) ;
|
pCrv->SetTempProp( nOrigSubCrv1 + 1, 0) ;
|
||||||
@@ -836,19 +828,10 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
|||||||
Point3d ptTemp ;
|
Point3d ptTemp ;
|
||||||
Vector3d vtDir ;
|
Vector3d vtDir ;
|
||||||
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
||||||
continue ;
|
return false ;
|
||||||
vtDir.Normalize() ;
|
vtDir.Normalize() ;
|
||||||
|
|
||||||
// verifico che il punto non sia già stato trovato
|
vResult.emplace_back( pt, vtDir) ;
|
||||||
bool bAdd = true ;
|
|
||||||
for ( int j = 0 ; j < ssize( vResult) ; j ++) {
|
|
||||||
if ( AreSamePointApprox( vResult[j].first, pt)) {
|
|
||||||
bAdd = false ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bAdd)
|
|
||||||
vResult.emplace_back( pt, vtDir) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1269,62 +1252,3 @@ Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
|
|||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
Voronoi::GetBisectorPointAtParam( int nCrv, double dPar, Point3d& ptP)
|
|
||||||
{
|
|
||||||
if ( ! IsValid())
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ( ! m_bVDComputed)
|
|
||||||
CalcVoronoi() ;
|
|
||||||
|
|
||||||
// verifico se il bisettore e il parametri richiesto sono sensati
|
|
||||||
if ( nCrv >= m_vroni->GetNumberOfEdges())
|
|
||||||
return false ;
|
|
||||||
double dParS, dParE ;
|
|
||||||
m_vroni->GetBisectorParams( nCrv, dParS, dParE) ;
|
|
||||||
if ( dParS > dParE)
|
|
||||||
swap( dParS, dParE) ;
|
|
||||||
if ( dPar < dParS || dPar > dParE)
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// calcolo il punto sul bisettore in corrispondenza dell'offset
|
|
||||||
m_vroni->GetBisectorPointAtParam( nCrv, dPar, ptP.v) ;
|
|
||||||
ptP.ToGlob( m_Frame) ;
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
Voronoi::GetBisectorSites( int nCrv, int& nCrv1, int& nSubCrv1, int& nSubPnt1, int& nCrv2, int& nSubCrv2, int& nSubPnt2)
|
|
||||||
{
|
|
||||||
if ( ! IsValid())
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ( ! m_bVDComputed)
|
|
||||||
CalcVoronoi() ;
|
|
||||||
|
|
||||||
// verifico se il bisettore è valido
|
|
||||||
if ( nCrv >= m_vroni->GetNumberOfEdges())
|
|
||||||
return false ;
|
|
||||||
|
|
||||||
// calcolo il punto sul bisettore in corrispondenza dell'offset
|
|
||||||
m_vroni->GetBisectorSites( nCrv, nCrv1, nSubCrv1, nSubPnt1, nCrv2, nSubCrv2, nSubPnt2) ;
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -60,8 +60,6 @@ class Voronoi
|
|||||||
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps = true) ;
|
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps = true) ;
|
||||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
|
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
|
||||||
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;
|
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;
|
||||||
bool GetBisectorPointAtParam( int nCrv, double dPar, Point3d& ptP) ;
|
|
||||||
bool GetBisectorSites( int nCrv, int& nCrv1, int& nSubCrv1, int& nSubPnt1, int& nCrv2, int& nSubCrv2, int& nSubPnt2) ;
|
|
||||||
|
|
||||||
bool Translate( const Vector3d& vtMove) ;
|
bool Translate( const Vector3d& vtMove) ;
|
||||||
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ;
|
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ;
|
||||||
|
|||||||
Reference in New Issue
Block a user