Compare commits

..

3 Commits

Author SHA1 Message Date
Daniele Bariletti 5897b93ab8 Merge branch 'master' into Trimming 2026-05-18 09:17:52 +02:00
Daniele Bariletti 1f79def16c EgtGeomKernel :
- modifica alla sincronizzazione tra curve per trimming.
2026-05-08 18:15:01 +02:00
Daniele Bariletti a4f0a43273 Merge branch 'master' into Trimming 2026-05-08 17:25:43 +02:00
22 changed files with 1614 additions and 4104 deletions
+612 -1175
View File
File diff suppressed because it is too large Load Diff
+16 -49
View File
@@ -2652,7 +2652,7 @@ ResetCurveVoronoi( const ICurve& crvC)
//----------------------------------------------------------------------------
bool
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert, bool bHaltOnFork)
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
{
if ( ssize( vCrv) == 1)
return true ;
@@ -2670,7 +2670,7 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert,
}
INTVECTOR vIds ;
Point3d ptStart = ORIG ;
while ( chainCrv.GetChainFromNear( ptStart, bHaltOnFork, vIds)) {
while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) {
int nFirst = vIds[0] ;
bool bInvert = false ;
if ( nFirst < 0)
@@ -2703,18 +2703,6 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert,
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
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) ;
double dSearchLen = dMyDist / 2 ;
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
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)
@@ -2817,41 +2800,25 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
// faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi
DBLVECTOR vVal ;
// [Controllo migliorabile, magari mendiante metodo di bisezione (?)]
double dMin = INFINITO ;
const double dCoeff = 0.1 ;
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
double dUStep2 ;
vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ;
if ( vVal.back() < dMin) {
dMin = vVal.back() ;
double dUStep2 ; pCrvEdge2->GetParamAtLength( dLen, dUStep2) ;
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
pCrvEdge2->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
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 ;
}
}
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 ;
}
}
dMin = dVal ;
}
}
}
// se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita
if ( bUpdated)
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
return true ;
}
+2 -1
View File
@@ -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 CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
BIN
View File
Binary file not shown.
-1
View File
@@ -324,7 +324,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="OffsetCurve3d.cpp" />
<ClCompile Include="Trimming.cpp" />
<ClCompile Include="MultiGeomDB.cpp" />
<ClCompile Include="SurfTriMeshOffset.cpp" />
-3
View File
@@ -576,9 +576,6 @@
<ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter>
</ClCompile>
<ClCompile Include="OffsetCurve3d.cpp">
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
+43 -161
View File
@@ -15,7 +15,6 @@
#include "stdafx.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkIntersLineCylinder.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
using namespace std ;
@@ -26,176 +25,99 @@ using namespace std ;
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight,
double& dU1, double& dU2)
{
dU1 = NAN ;
dU2 = NAN ;
// Verifico il versore
if ( vtV.IsSmall())
// Verifico il versore
if ( vtL.IsSmall())
return false ;
// Verifico il cilindro
if ( dRad < EPS_SMALL || dH < EPS_SMALL)
// Verifico il cilindro
if ( dRad < EPS_SMALL || dHeight < EPS_SMALL)
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 ;
if ( abs( vtV.z) > EPS_ZERO) {
if ( abs( vtL.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
if ( bIgnoreTap)
dEpsRad = 0. ;
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
dU1 = ( ptInt1 - ptL) * vtL ;
nBasInt += 1 ;
vtN1 = - Z_AX ;
dU1 = ( ( 0 - ptP.z) / vtV.z) ;
}
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
dU2 = ( ptInt2 - ptL) * vtL ;
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 ( dU1 > dU2) {
if ( dU1 > dU2)
swap( dU1, dU2) ;
swap( ptInt1, ptInt2) ;
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
// 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} ;
// Determino le intersezioni con la superficie laterale del cilindro
DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad,
2 * ( ptL.x * vtL.x + ptL.y * vtL.y),
vtL.x * vtL.x + vtL.y * vtL.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) ;
if ( bIgnoreTap) {
dEpsLow = 0. ;
dEpsUp = 0. ;
}
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
// 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)
double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ;
if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL)
-- nRoot ;
}
if ( nRoot >= 1) {
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ;
if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) {
if ( nRoot == 2)
vdRoots[0] = vdRoots[1] ;
-- nRoot ;
}
}
// Due soluzioni: la retta interseca due volte la superficie laterale
// 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 ;
dU1 = vdRoots[0] ;
dU2 = vdRoots[1] ;
// Determino le normali
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
vtN1.Normalize() ;
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
vtN2.Normalize() ;
if ( dU1 > dU2) {
if ( dU1 > dU2)
swap( dU1, dU2) ;
swap( ptInt1, ptInt2) ;
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
// Trovate intersezioni
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) {
// Se piano superiore
// Se piano superiore
if ( nBasInt == 2) {
// Punto di intersezione
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) {
// Punto di intersezione
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
return false ;
if ( dU1 > dU2) {
if ( dU1 > dU2)
swap( dU1, dU2) ;
swap( ptInt1, ptInt2) ;
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
// Trovate intersezioni
return true ;
}
// Nessuna soluzione : nessuna intersezione
// Nessuna soluzione : nessuna intersezione
else
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.
// 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))
return false ;
// Ora eseguo i conti nel riferimento intrinseco
bool bTapLow = false ;
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) ;
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
}
//----------------------------------------------------------------------------
@@ -228,7 +144,7 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
bool
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
double& dU1, double& dU2)
double& dU1, double& dU2)
{
// Determino asse ed altezza del cilindro
Vector3d vtCyl = ptCyl2 - ptCyl1 ;
@@ -241,39 +157,5 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
if ( ! frCyl.Set( ptCyl1, vtCyl))
return false ;
// Ora eseguo i conti nel riferimento intrinseco
bool bTapLow = false ;
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) ;
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
}
+4 -23
View File
@@ -20,27 +20,17 @@
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, 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) ;
// 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) ;
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight,
double& dU1, double& dU2) ;
//----------------------------------------------------------------------------
inline bool
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight)
{
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
bool bTapLow = false, bTapUp = false ;
bool bIgnoreTap = true ;
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ;
}
//----------------------------------------------------------------------------
@@ -60,12 +50,3 @@ bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
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) ;
-646
View File
@@ -1,646 +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/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 ;
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)
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 && 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 ;
}
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.866) {
// 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 ptP ; vOffsetCrvs.front().pCrv->GetStartPoint( ptP) ;
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
// 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 ;
// 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 = 10 * 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 ;
}
-10
View File
@@ -1618,9 +1618,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
int nPnt2 = PL2.GetPointNbr() ;
if ( nPnt1 == 0 || nPnt2 == 0)
return false ;
bool bClosed1 = PL1.IsClosed() ;
bool bClosed2 = PL2.IsClosed() ;
// indica la presenza di punti interni in comune tra le due polylines
bCommonInternalPoints = false ;
@@ -1666,10 +1663,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
if ( 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
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
bCommonInternalPoints = true ;
@@ -1700,9 +1693,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
if ( 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)
bCommonInternalPoints = true ;
+25 -320
View File
@@ -13,7 +13,6 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include <cmath>
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "GeoConst.h"
@@ -33,6 +32,14 @@ using namespace std ;
const double COS_ANG_LIM = 0.0175 ;
// Angolo massimo tra normali per effettuare bisezione su spigolo
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
@@ -57,7 +64,6 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
static bool
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
{
const double dSinSmallAngle = sin( 0.5 * DEGTORAD) ;
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
// precedente
int j = i - 1 ;
@@ -73,34 +79,18 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Point3d ptInt ;
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
// verifico se spigolo convesso o concavo
double dProjPrev = ( vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 ;
double dProjCurr = ( vPt5ax[j].ptP - vPt5ax[i].ptP) * vPt5ax[i].vtDir1 ;
bool bConvex = ( abs( dProjCurr) > abs( dProjPrev) ? dProjCurr < 0 : dProjPrev < 0) ;
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 ;
}
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 bValidInters = ( bValidIntersAfterJ && bValidIntersBeforeI) ;
bool bConvex ;
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
else
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
// se convesso, metto due punti con direzione appena prima e appena dopo
if ( bConvex) {
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
if ( dLen1 > 10 * EPS_SMALL && bValidIntersAfterJ) {
if ( dLen1 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
if ( bValidInters)
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.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
@@ -112,14 +102,9 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
}
else
vPt5ax[j].nFlag = P5AX_CVEX ;
if ( dLen2 > 10 * EPS_SMALL && bValidIntersBeforeI) {
if ( dLen2 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
if ( bValidInters)
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.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
@@ -148,63 +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 ( bConvex) {
vPt5ax[i].nFlag = P5AX_CVEX ;
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 ;
}
@@ -416,7 +344,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar
//----------------------------------------------------------------------------
bool
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
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
@@ -436,100 +364,21 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
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 ;
Vector3d vtNormPrev = V_INVALID ;
Point3d ptPrev ;
bool bFirst = true ;
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// controllo che la normale trovata sia in linea con la precedente, se i due tratti erano abbastanza allineati
bool bRecalc = false ;
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)) {
if ( Pt5axRec.vtDir1 * Pt5ax.vtDir1 < COS_ANG_MAX_CORNER) {
vPt5ax.back().vtDir1 = Pt5axRec.vtDir1 ;
vPt5ax.back().vtDir2 = Pt5axRec.vtDir2 ;
}
}
}
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 ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
if ( ! AddPointsOnCorners( vPt5ax))
return false ;
}
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
@@ -1252,147 +1101,3 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
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 ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza
double dPar, 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 ;
Vector3d vtNormPrev = V_INVALID ;
Point3d ptPrev ;
bool bFirst = true ;
const ICurveComposite* pCC = GetCurveComposite( &crCrv) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
Pt5ax.ptP = ptP ;
Pt5ax.dPar = dPar ;
double dDecimal ;
int nCrv = int( modf( dPar, &dDecimal) == 0.0 ? dPar - 1 : dPar) ;
if ( nCrv < 0)
nCrv = 0 ;
int nTria ; pCC->GetCurveTempProp( nCrv, nTria, 0) ;
Triangle3d trTria ; pSurf.GetTriangle( nTria, trTria) ;
Pt5ax.vtDir1 = trTria.GetN() ;
Pt5ax.vtDir2 = Pt5ax.vtDir1 ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.nFlag = P5AX_STD ;
vPt5ax.emplace_back( Pt5ax) ;
/*if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;*/
///////////////////////////////////////////// questa parte non dovrebbe servire più visto che so già qual'è il triangolo giusto per guardare la normale
//// controllo che la normale trovata sia in linea con la precedente, se i due tratti erano abbastanza allineati
//bool bRecalc = false ;
//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)) {
// if ( Pt5axRec.vtDir1 * Pt5ax.vtDir1 < COS_ANG_MAX_CORNER) {
// vPt5ax.back().vtDir1 = Pt5axRec.vtDir1 ;
// vPt5ax.back().vtDir2 = Pt5axRec.vtDir2 ;
// }
// }
//}
//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 = vtDirNext * vtDirPrev ;
if ( dProj > COS_ANG_MAX_CORNER)
vtDir = Media( vtDirNext, 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
if ( bSharpEdges) {
if ( ! AddPointsOnCorners( vPt5ax))
return false ;
}
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
+551 -1357
View File
File diff suppressed because it is too large Load Diff
+154 -77
View File
@@ -5976,6 +5976,103 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
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
static bool
@@ -6087,7 +6184,7 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
// ---------------------------------------------------------------------------
// Calcolo delle Curve di Sync per evitare Twist
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
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 int NUM_SAMPLE_PNT = 20 ;
const int nStepSkip = NUM_SAMPLE_PNT / 10 ;
#if DEBUG_CURVATURE
vector<pair<Point3d, double>> _vPtK1 ;
vector<pair<Point3d, double>> _vPtK2 ;
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
#endif
int nLastSync = ssize( vSyncLines) ;
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine della prima curva di Bordo
Vector3d vtS1 ; pSubEdge1->GetStartDir( vtS1) ;
Vector3d vtE1 ; pSubEdge1->GetEndDir( vtE1) ;
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) ;
if ( bSplit1) {
// Individuo il punto a Curvatura Massima
pSubEdge1->GetLength( dLen1) ;
double dKMax1 = - INFINITO + 1, dUK1Max = - EPS_SMALL ;
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
double dCurrLen1 = Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1) ;
double dUCurr1 ; pSubEdge1->GetParamAtLength( dCurrLen1, dUCurr1) ;
@@ -6145,21 +6237,22 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
vtTanKMax1Next.Normalize() ;
// Calcolo la nuova linea di sincronizzazione
CurvaturePoint myCurvaturePoint( dUK1Max, ptKMax1, vtTanKMax1Prev, vtTanKMax1Next) ;
double dUOn2 ; double dLenCurr2 ;
GetIsoPointOnSecondCurve( pSubEdge1, pSubEdge2, dUK1Max, dUOn2, dMyDist, 0, 0, dLenCurr2, dLen2) ;
Point3d ptOn2 ; pSubEdge2->GetPointD1D2( dUOn2, ICurve::FROM_MINUS, ptOn2) ;
vSyncLines.emplace_back( ptKMax1, ptOn2) ;
BIPOINT SyncLine ;
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge2, SyncLine) ;
vSyncLines.emplace_back( SyncLine) ;
}
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto per la prima curva di Bordo
Vector3d vtS2 ; pSubEdge2->GetStartDir( vtS2) ;
Vector3d vtE2 ; pSubEdge2->GetEndDir( vtE2) ;
double dLen2 = - EPS_SMALL ;
bool bSplit2 = ( vtS2 * vtE2 < COS_LIMIT) ;
if ( bSplit2) {
// Individuo il punto a Curvatura Massima
pSubEdge2->GetLength( dLen2) ;
double dKMax2 = - INFINITO + 1, dUK2Max = - EPS_SMALL ;
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
double dCurrLen2 = Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2) ;
double dUCurr2 ; pSubEdge2->GetParamAtLength( dCurrLen2, dUCurr2) ;
@@ -6187,10 +6280,11 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
vtTanKMax2Next.Normalize() ;
// Calcolo la nuova linea di sincronizzazione
CurvaturePoint myCurvaturePoint( dUK2Max, ptKMax2, vtTanKMax2Prev, vtTanKMax2Next) ;
double dUOn1 ; double dLenCurr1 ;
GetIsoPointOnSecondCurve( pSubEdge2, pSubEdge1, dUK2Max, dUOn1, dMyDist, 0, 0, dLenCurr1, dLen1) ;
Point3d ptOn1 ; pSubEdge1->GetPointD1D2( dUOn1, ICurve::FROM_MINUS, ptOn1) ;
vSyncLines.emplace_back( ptOn1, ptKMax2) ;
BIPOINT SyncLine ;
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge1, SyncLine) ;
// !<-- Inverto la curva di Sincronizzaione per coerenza con la prima -->!
swap( SyncLine.first, SyncLine.second) ;
vSyncLines.emplace_back( SyncLine) ;
}
#if DEBUG_CURVATURE // Curvatura minima -> AQUA | Curvatura massima -> ORANGE
@@ -6235,7 +6329,7 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
#endif
// Se non ho alcuna linea di sincronizzazione, non faccio nulla
if ( vSyncLines.empty() || ( ! bSplit2 && ! bSplit1))
if ( vSyncLines.empty())
return true ;
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. Così facendo evito anche di creare curve di Sync lungo le diagonali della Quadrangolazione
const double LEN_TOL = 2. ;
const double dParTol = 0.1 ;
double dLenPrev1 = - LEN_TOL, dLenPrev2 = - LEN_TOL ;
for ( int i = nLastSync ; i < ssize( vSyncLines) ; ++ i) {
for ( int i = 0 ; i < ssize( vSyncLines) ; ++ i) {
double dSyncLen1 ; pSubEdge1->GetLengthAtPoint( vSyncLines[i].first, dSyncLen1, TOL) ;
bool bErase = ( dSyncLen1 < max( LEN_TOL, dParTol * dLen1) || dSyncLen1 - dLenPrev1 < LEN_TOL) ;
bEraseLastIso = dSyncLen1 > min( dLen1 - LEN_TOL, ( 1 - dParTol) * dLen1) ;
bool bErase = ( dSyncLen1 < max( LEN_TOL, 0.2 * dLen1) || dSyncLen1 > min( dLen1 - LEN_TOL, 0.8 * dLen1)) ;
if ( ! bErase) {
double dSyncLen2 ; pSubEdge2->GetLengthAtPoint( vSyncLines[i].second, dSyncLen2, TOL) ;
bErase = ( dSyncLen2 < max( LEN_TOL, dParTol * dLen2) || dSyncLen2 - dLenPrev2 < LEN_TOL) ;
bEraseLastIso = bEraseLastIso || dSyncLen2 > min( dLen2 - LEN_TOL, ( 1 - dParTol) * dLen2) ;
dLenPrev2 = dSyncLen2 ;
bErase = ( dSyncLen2 < max( LEN_TOL, 0.2 * dLen2) || dSyncLen2 > min( dLen2 - LEN_TOL, 0.8 * dLen2)) ;
}
if ( bErase && ! bEraseLastIso) {
if ( bErase) {
vSyncLines.erase( vSyncLines.begin() + i) ;
-- i ;
}
dLenPrev1 = dSyncLen1 ;
if ( bEraseLastIso)
break ;
}
if ( vSyncLines.empty())
return true ;
// Se due curve di Sincronizzazione rimaste
if ( ssize( vSyncLines) - nLastSync == 2) {
if ( ssize( vSyncLines) == 2) {
// Se si sovrappongono, ne elimino una
if ( AreSamePointEpsilon( vSyncLines.end()[-2].first, vSyncLines.end()[-1].first, LEN_TOL) &&
AreSamePointEpsilon( vSyncLines.end()[-2].second, vSyncLines.end()[-1].second, LEN_TOL))
if ( AreSamePointEpsilon( vSyncLines[0].first, vSyncLines[1].first, LEN_TOL) &&
AreSamePointEpsilon( vSyncLines[0].second, vSyncLines[1].second, LEN_TOL))
vSyncLines.pop_back() ;
}
// 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
double dU0 ; pSubEdge1->GetParamAtPoint( vSyncLines.end()[-2].first, dU0, TOL) ;
double dU1 ; pSubEdge1->GetParamAtPoint( vSyncLines.end()[-1].first, dU1, TOL) ;
double dU0 ; pSubEdge1->GetParamAtPoint( vSyncLines[0].first, dU0, TOL) ;
double dU1 ; pSubEdge1->GetParamAtPoint( vSyncLines[1].first, dU1, TOL) ;
if ( dU0 > dU1 - EPS_SMALL)
swap( vSyncLines.end()[-2], vSyncLines[-1]) ;
swap( vSyncLines[0], vSyncLines[1]) ;
// Verifico che le curve non si intreccino
pSubEdge2->GetParamAtPoint( vSyncLines.end()[-2].second, dU0, TOL) ;
pSubEdge2->GetParamAtPoint( vSyncLines.end()[-1].second, dU1, TOL) ;
pSubEdge2->GetParamAtPoint( vSyncLines[0].second, dU0, TOL) ;
pSubEdge2->GetParamAtPoint( vSyncLines[1].second, dU1, TOL) ;
if ( dU0 > dU1 - EPS_SMALL)
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 ;
}
@@ -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
dLenCurr1 = Clamp( dLenPrev1 + dMyDist, 0., dLen1) ;
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
// se sono abbastanza vicino ad una joint allora prendo quel punto
double dUClosestJoint1 = round( dUCurr1) ;
double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
if ( abs( dLenCurr1 - dLenAlt1) < 1)
dUCurr1 = dUClosestJoint1 ;
//// se sono abbastanza vicino ad una joint allora prendo quel punto
//double dUClosestJoint1 = round( dUCurr1) ;
//double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
//if ( abs( dLenCurr1 - dLenAlt1) < 1)
// dUCurr1 = dUClosestJoint1 ;
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
vtCurr1.Normalize() ;
@@ -6355,17 +6437,14 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
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
//double dUClosestJoint2 = round( dUCurr2) ;
//double dLenAlt2 = 0 ; pCrvEdge2->GetLengthAtParam( dUClosestJoint2, dLenAlt2) ;
//if ( abs( dLenCurr2 - dLenAlt2) < 1) {
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptNewJoint) ;
// if ( pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint))
// dUCurr2 = dUClosestJoint2 ;
//if ( abs( dLenCurr1 - dLenAlt2) < 1) {
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUClosestJoint2, ICurve::FROM_MINUS, ptNewJoint) ;
// pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint) ;
// dUCurr2 = dUClosestJoint2 ;
//}
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
#if DEBUG_SYNCLINES
@@ -6376,6 +6455,10 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
#endif
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 ---
// 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
@@ -6383,21 +6466,25 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
PtrOwner<ICurveComposite> pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ;
BIPNTVECTOR 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 ---
// 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
// -->! NB. Queste linee vengono create considerando le SubQuadrangolazioni con gli Spigoli. !<--
BIPNTVECTOR vTwistSyncLines ;
bool bEraseLastIso = false ;
if ( vEdgeSyncLines.empty())
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines, bEraseLastIso) ;
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines) ;
else {
BIPOINT SyncLinePrev, SyncLineNext ;
pCrvQuad1->GetStartPoint( SyncLinePrev.first) ;
pCrvQuad2->GetStartPoint( SyncLinePrev.second) ;
for ( int i = 0 ; i <= ssize( vEdgeSyncLines) ; ++ i) {
if ( i == ssize( vEdgeSyncLines)) {
for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
if ( i == ssize( vEdgeSyncLines) - 1) {
pCrvQuad1->GetEndPoint( SyncLineNext.first) ;
pCrvQuad2->GetEndPoint( SyncLineNext.second) ;
}
@@ -6412,21 +6499,13 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
pCrvQuad1->GetParamAtPoint( SyncLineNext.first, dUE1) ;
pCrvQuad2->GetParamAtPoint( SyncLineNext.second, dUE2) ;
PtrOwner<ICurveComposite> pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ;
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUS2, dUE2))) ;
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines, bEraseLastIso) ;
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUE1, dUE2))) ;
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines) ;
// Aggiorno i parametri
SyncLinePrev = SyncLineNext ;
}
bEraseLastIso = false ;
}
if ( bEraseLastIso) {
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)
// aggiungo le nuove curve ( non importa che siano in ordine di parametro)
vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.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") ;
#endif
// devo riempire 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 ( dLastParam0 - vIso[c].dParam0 < EPS_ZERO)
vIso[c].dParam0 = dLastParam0 + EPS_PARAM ;
else {
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be created with the isocurves provided") ;
else
return false ;
}
}
if ( vIso[c].dParam1 < dLastParam1) {
if ( dLastParam1 - vIso[c].dParam1 < EPS_ZERO)
vIso[c].dParam1 = dLastParam1 + EPS_PARAM ;
else {
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be created with the isocurves provided") ;
else
return false ;
}
}
dLastParam0 = vIso[c].dParam0 ;
dLastParam1 = vIso[c].dParam1 ;
+15 -41
View File
@@ -1150,7 +1150,7 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
//----------------------------------------------------------------------------
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
if ( m_nStatus != OK)
@@ -1163,7 +1163,6 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
// Controlli su tolleranza
dTol = max( dTol, 100 * EPS_SMALL) ;
double dMyLinTol = max( EPS_SMALL, dLinTol) ;
// Determino il riferimento di proiezione
Frame3d frOCS ; frOCS.Set( ORIG, vtVers) ;
@@ -1189,10 +1188,8 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ;
else {
if ( ! pSfr->Add( *pSfrTria))
return false ;
}
else
pSfr->Add( *pSfrTria) ;
}
}
// passo al successivo
@@ -1204,18 +1201,14 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
return false ;
// Effettuo contro-offset
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
return false ;
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
// Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ;
if ( ! pSfr->ApproxLoopWithLines( i, j, dMyLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
vPL.clear() ;
return false ;
}
vPL.emplace_back( PL) ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.emplace_back( PL) ;
}
}
@@ -1224,7 +1217,7 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
//----------------------------------------------------------------------------
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
if ( m_nStatus != OK)
@@ -1237,7 +1230,6 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
// Controlli su tolleranza
dTol = max( dTol, 100 * EPS_SMALL) ;
double dMyLinTol = max( EPS_SMALL, dLinTol) ;
// Determino il riferimento di proiezione
Frame3d frOCS ; frOCS.Set( plPlane.GetPoint(), vtVers) ;
@@ -1267,10 +1259,8 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ;
else {
if ( ! pSfr->Add( *pSfrTria))
return false ;
}
else
pSfr->Add( *pSfrTria) ;
}
}
}
@@ -1284,18 +1274,14 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
return true ;
// Effettuo contro-offset
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
return false ;
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
// Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ;
if ( ! pSfr->ApproxLoopWithLines( i, j, dMyLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
vPL.clear() ;
return false ;
}
vPL.emplace_back( PL) ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.emplace_back( PL) ;
}
}
@@ -3824,19 +3810,12 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
BBox3d b3Box ;
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> vInnerShells ;
INTVECTOR vOpenShells ;
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
// se la shell è chiusa
if ( ssize( mShellTria[nSh]) >= 4 && IsShellClosed( nSh)) {
if ( IsShellClosed( nSh)) {
// creo una superficie clonata dalla shell
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
@@ -3848,9 +3827,7 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
BBox3d b3Box ;
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
// la inserisco nel vettore opportuno
if ( abs( dVol) < 1 * 1 * EPS_SMALL)
vOpenShells.push_back( nSh) ;
else if ( dVol > 0)
if ( dVol > 0)
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
else
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
@@ -4002,7 +3979,6 @@ SurfTriMesh::IsShellClosed( int nShell) const
return false ;
// ciclo sui triangoli della shell
bool bClosed = true ;
int nTriaCnt = 0 ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// se triangolo non cancellato e della shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
@@ -4013,12 +3989,10 @@ SurfTriMesh::IsShellClosed( int nShell) const
bClosed = false ;
break ;
}
else
++ nTriaCnt ;
}
}
// restituisco il risultato
return ( bClosed && nTriaCnt >= 4) ;
return bClosed ;
}
//----------------------------------------------------------------------------
+2 -3
View File
@@ -16,7 +16,6 @@
#include "ObjGraphicsMgr.h"
#include "DllMain.h"
#include "GeoObjRW.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "/EgtDev/Include/EGkHashGrids3d.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
@@ -296,8 +295,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
SurfTriMesh* CloneTriangle( int nT) 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 Plane3d& plPlane, 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) const override ;
int GetFacetCount( void) const override ;
int GetFacetSize( void) const override
{ return int( m_vFacet.size()) ; }
+42 -127
View File
@@ -3533,11 +3533,10 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d
//-----------------------------------------------------------------------------
static bool
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
const Plane3d& plStart, const Plane3d& plEnd, const Vector3d vtAuxStart, const Vector3d vtAuxEnd,
double dLinTol, BIPNTVECTOR& vBiPts)
const Plane3d& plStart, const Plane3d& plEnd, double dLinTol,
BIPNTVECTOR& vBiPts)
{
vBiPts.clear() ;
const double dLinAngTol = 15 * EPS_SMALL ; // tolleranza sulla lunghezza della corda dell'angolo di tolleranza
// Verifico che le curve siano valide
if ( pGuide == nullptr || ! pGuide->IsValid() ||
@@ -3567,134 +3566,52 @@ InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICur
// Interpolo le normali dei piani rispetto a tale valore
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
vtN.Normalize() ;
Vector3d vtAux = Media( vtAuxStart, vtAuxEnd, dInterPar) ; vtAux.Normalize() ;
// Definisco il piano di intersezione
Point3d ptCurr ;
if ( ! pCrv->GetEndPoint( ptCurr))
return false ;
// con i piani
#if DEBUG_SYNC_INTERPOLATION
Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
VT.emplace_back( Release( frCurr)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
// Recupero il parametro di intersezione tra la curva e il piano
#if DEBUG_SYNC_INTERPOLATION
if ( false) {
VT.clear() ; VC.clear() ;
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
VT.emplace_back( Release( PT)) ;
VC.emplace_back( AQUA) ;
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
VECT->ChangeBase( ptCurr) ;
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
pSfrPlane->AddExtLoop( Release( pArc)) ;
VT.emplace_back( Release( pSfrPlane)) ;
VC.emplace_back( Color( 0., 0., 0., .5)) ;
VT.emplace_back( Release( VECT)) ;
VC.emplace_back( BLUE) ;
VT.emplace_back( pOtherGuide->Clone()) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
}
#if 0
VT.clear() ; VC.clear() ;
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
VT.emplace_back( Release( PT)) ;
VC.emplace_back( AQUA) ;
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
VECT->ChangeBase( ptCurr) ;
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
pSfrPlane->AddExtLoop( Release( pArc)) ;
VT.emplace_back( Release( pSfrPlane)) ;
VC.emplace_back( Color( 0., 0., 0., .5)) ;
VT.emplace_back( Release( VECT)) ;
VC.emplace_back( BLUE) ;
VT.emplace_back( pOtherGuide->Clone()) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
bool bFound = false ;
if ( IntCP.GetIntersCount() != 0) {
// Recupero il punto della prima intersezione trovata
Point3d ptIntClosest ;
double dPar ;
IntCP.GetIntersPointNearTo( ptCurr, ptIntClosest, dPar) ;
// verifico che sia allineato con la direzione che dovrebbe avere
Vector3d vtDir = ptIntClosest - ptCurr ;
vtDir.Normalize() ;
double dDiff = (vtDir - vtAux).Len() ;
if ( dDiff < dLinAngTol) {
#if DEBUG_SYNC_INTERPOLATION
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptIntClosest) ;
VT.emplace_back( Release( ptG)) ;
VC.emplace_back( WHITE) ;
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)) ;
}
if ( IntCP.GetIntersCount() == 0)
return false ; // ambiguità
// Recupero il punto della prima intersezione trovata
Point3d ptInt ;
double dPar ;
if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar))
return false ;
#if DEBUG_SYNC_INTERPOLATION
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ;
VT.emplace_back( Release( ptG)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
// Memorizzo tale punto
vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ;
}
return true ;
@@ -4149,18 +4066,18 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
Vector3d vtStart1, vtStart2 ;
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
return false ;
Vector3d vtAuxStart = ptE1 - ptS1 ; vtAuxStart.Normalize() ;
Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ;
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
Vector3d vtN = OrthoCompo( vtMTan, vtAuxStart) ; vtN.Normalize() ;
Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
Plane3d plStart ;
if ( ! plStart.Set( ptS1, vtN))
return false ;
Vector3d vtEnd1, vtEnd2 ;
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
return false ;
Vector3d vtAuxEnd = ptE2 - ptS2 ; vtAuxEnd.Normalize() ;
vtAux = ptE2 - ptS2 ; vtAux.Normalize() ;
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
vtN = OrthoCompo( vtMTan, vtAuxEnd) ; vtN.Normalize() ;
vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
Plane3d plEnd ;
if ( ! plEnd.Set( ptS2, vtN))
return false ;
@@ -4179,15 +4096,13 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2
BIPNTVECTOR vBiPts1 ;
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts1))
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1))
return false ;
vtAuxStart *= -1 ;
vtAuxEnd *= -1 ;
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1
BIPNTVECTOR vBiPts2 ;
//if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts2))
// return false ;
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2))
return false ;
// Restituisco le Curve di Sincronizzazione
// [Da Bordo 1 a Bordo 2 originale]
+3
View File
@@ -393,6 +393,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
double& dU1, double& dU2) 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 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,
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
bool bTapLow, bool bTapUp,
+121
View File
@@ -2071,6 +2071,127 @@ VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise)
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.
// La funzione restituisce true in caso di intersezione, false altrimenti.
+4 -6
View File
@@ -21,7 +21,6 @@
#include "CurveLine.h"
#include "CurveArc.h"
#include "GeoConst.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h"
@@ -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 ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
ptInt1, vtN1, ptInt2, vtN2)) {
if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool, nTool) ;
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ;
else
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
}
}
}
+15 -21
View File
@@ -21,7 +21,6 @@
#include "VolZmap.h"
#include "GeoConst.h"
#include "IntersLineBox.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
@@ -6250,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 ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
}
}
@@ -6296,9 +6294,8 @@ VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
Vector3d vtN1, vtN2 ;
// Cilindro
double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
}
@@ -6477,8 +6474,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
// Cilindro iniziale
CylFrame.ChangeOrig( ptITip) ;
double dU1, dU2 ;
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) ;
}
@@ -6486,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
// il vettore che congiunge le due origini.
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) ;
}
@@ -7073,8 +7069,7 @@ VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe,
// Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
}
}
@@ -7222,15 +7217,15 @@ VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, cons
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
ptInt1, vtN1, ptInt2, vtN2)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
}
if ( IntersLineCyl( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
ptInt1, vtN1, ptInt2, vtN2)) {
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,
@@ -7626,9 +7621,8 @@ VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double
// Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
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()) ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
}
}
}
+5 -81
View File
@@ -434,7 +434,6 @@ Voronoi::GetBisectorCurve( int i)
pLine->Set( ptS, ptE) ;
pLine->SetTempParam( dParS, 0) ;
pLine->SetTempParam( dParE, 1) ;
pLine->SetTempProp( i) ;
pLine->ToGlob( m_Frame) ;
return pLine ;
}
@@ -455,7 +454,6 @@ Voronoi::GetBisectorCurve( int i)
pArc->SetC2P( ptC, ptS, ptE) ;
pArc->SetTempParam( dParS, 0) ;
pArc->SetTempParam( dParS, 1) ; // dParE = dParS
pArc->SetTempProp( i) ;
pArc->ToGlob( m_Frame) ;
return pArc ;
}
@@ -475,7 +473,7 @@ Voronoi::GetBisectorCurve( int i)
bool bInvert = false ;
double dPar1, dPar2 ;
m_vroni->GetApproxedBisectorParams( i, dPar1, dPar2) ;
if ( dPar1 > dPar2)
if ( dPar1 > dPar2 + EPS_SMALL)
bInvert = true ;
// punto iniziale
@@ -498,11 +496,6 @@ Voronoi::GetBisectorCurve( int i)
dParPrev = dPar ;
nCrvCount ++ ;
}
else if ( ( bInvert && j == 0) || ( ! bInvert && j == nPoints - 1)) {
// se estremo devo forzarlo
pCompo->ModifyEnd( pt) ;
dParPrev = dPar ;
}
// aggiorno per punto successivo
if ( bInvert)
j -- ;
@@ -513,7 +506,6 @@ Voronoi::GetBisectorCurve( int i)
// setto parametri sulla curva
pCompo->SetTempParam( dParS, 0) ;
pCompo->SetTempParam( dParPrev, 1) ;
pCompo->SetTempProp( i) ;
pCompo->ToGlob( m_Frame) ;
return pCompo ;
@@ -708,8 +700,8 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
if ( bLeft && bRight) {
// recupero i siti di riferimento
int nOrigCrv1, nOrigSubCrv1, nOrigSubPnt1, nOrigCrv2, nOrigSubCrv2, nOrigSubPnt2 ;
m_vroni->GetBisectorSites( i, nOrigCrv1, nOrigSubCrv1, nOrigSubPnt1, nOrigCrv2, nOrigSubCrv2, nOrigSubPnt2) ;
int nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2 ;
m_vroni->GetBisectorSites( i, nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2) ;
if ( nOrigCrv1 != -1) {
// verifico il lato rispetto al primo sito
pCrv->SetTempProp( nOrigSubCrv1 + 1, 0) ;
@@ -836,19 +828,10 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
Point3d ptTemp ;
Vector3d vtDir ;
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
continue ;
return false ;
vtDir.Normalize() ;
// verifico che il punto non sia già stato trovato
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) ;
vResult.emplace_back( pt, vtDir) ;
}
}
@@ -1269,62 +1252,3 @@ Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
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 ;
}
}
-2
View File
@@ -60,8 +60,6 @@ class Voronoi
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps = true) ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
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 Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ;