EgtGeomKernel :

- correzioni e migliorie a offset3d
- creato enum per angoli di una curva proiettata su superficie.
- aggiunta funzione per l'estensione delle superfici.
This commit is contained in:
Daniele Bariletti
2026-06-24 15:14:50 +02:00
parent 0c7f3d5fd8
commit 1c4198d31c
3 changed files with 185 additions and 40 deletions
+31 -23
View File
@@ -61,7 +61,7 @@ OffsetCurve3d::Reset( void)
//----------------------------------------------------------------------------
bool
OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOffDist, int nType)
OffsetCurve3d::Make( const PNT5AXVECTOR& vPnt5Ax, double dOffDist, int nType)
{
// la funzione è pensata per lavorare con il risultato dell'operazione ProjectCurveOnSurf
@@ -70,6 +70,18 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff
// 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 ;
@@ -116,25 +128,6 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff
bool bClosed = pCrv->IsClosed() ;
INTVECTOR vFlag ;
vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ;
const ICurve* pSubCrv = pCrv->GetFirstCurve() ;
const double dSinAngSmall = sin( 1 * DEGTORAD) ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
pSubCrv = pCrv->GetNextCurve() ;
Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ;
vtDirCurr.Normalize() ;
int nFlag ;
double dProj = vtDirCurr * vOffDir[i-1] ;
if ( dProj > dSinAngSmall)
nFlag = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ;
else if ( dProj > - dSinAngSmall)
nFlag = OffsetCurve3d::AngType::ANG_STR ;
else
nFlag = OffsetCurve3d::AngType::ANG_CVEX ;
vFlag.push_back( nFlag) ;
}
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 &&
@@ -148,12 +141,23 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff
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 ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
for ( int i = 1 ; i <= pCrv->GetCurveCount() ; ++i) {
pCrvCurr = pCrv->GetNextCurve() ;
if ( pCrvCurr == nullptr && bClosed && vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX)
pCrvCurr = pCrv->GetFirstCurve() ;
Vector3d vtOffDir = vOffDir[i] ;
Vector3d vtDirCurr ; pCrvCurr->GetStartDir( vtDirCurr) ;
pCrvPrev->GetStartDir( vtDirPrev) ;
@@ -239,7 +243,8 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff
Point3d ptP ; vOffsetCrvs.front().pCrv->GetStartPoint( ptP) ;
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ;
if ( pCL->IsValid())
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ;
}
// qui faccio la correzione per gli angoli interni
@@ -400,7 +405,10 @@ CalcAdjustConcavePartsInPath( const ICurveComposite* pCrv, const OFFSETSEGVEC& v
while ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
vLines.push_back( i) ;
++i ;
nFlag = vOffsetCrvs[i].nFlag ;
if ( i < ssize( vOffsetCrvs))
nFlag = vOffsetCrvs[i].nFlag ;
else
nFlag = OffsetCurve3d::AngType::ANG_STR ;
}
CYLVECT vCyl ;
// creo un cilindro della dimensione del raggio
+42 -17
View File
@@ -32,15 +32,6 @@ 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
const int P5AX_SMOOTH_CONC = 6 ; // zona concava curva, senza spigolo netto
//----------------------------------------------------------------------------
static double
@@ -65,7 +56,7 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
static bool
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
{
const double dSinSmallAngle = sin( 0 * DEGTORAD) ;
const double dSinSmallAngle = sin( 0.5 * DEGTORAD) ;
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
// precedente
int j = i - 1 ;
@@ -160,7 +151,10 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
// 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() ;
if ( vtDirNext * vPt5ax[j].vtDir1 > dSinSmallAngle) {
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 ;
}
@@ -382,7 +376,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)
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax, bool bNormOrTang)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
@@ -402,16 +396,47 @@ 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 ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
double dPar, dParNext ;
Point3d ptP, ptPNext ;
Vector3d vtDirPrev = V_INVALID ;
if ( PL.IsClosed()) {
Point3d pt1, pt2 ;
PL.GetLastLine( pt1, pt2) ;
vtDirPrev = pt2 - pt1 ;
}
bool bFound = PL.GetFirstULine( &dPar, &ptP, &dParNext, &ptPNext) ;
Vector3d vtFirst = ptPNext - ptP ;
bool bClosed = PL.IsClosed() ;
bool bLast = false ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
// se richiesta la tangente anziché la normale allora modifico il vettore associato al punto
Vector3d vtDir ;
if ( ! bNormOrTang) {
Vector3d vtNorm = vPt5ax.back().vtDir1 ;
if ( ! bLast)
vtDir = ptPNext - ptP ;
else if ( bClosed)
vtDir = vtFirst ;
else
vtDir = vtDirPrev ;
vtDirPrev = vtDir ;
if ( vtDirPrev.IsValid())
vtDir = Media( vtDir, vtDirPrev) ;
Vector3d vtTang = vtDir ^ vtNorm ; vtTang.Normalize() ;
vPt5ax.back().vtDir1 = vtTang ;
vPt5ax.back().vtDir2 = vtTang ;
}
// passo al successivo
bFound = PL.GetNextULine( &dPar, &ptP, &dParNext, &ptPNext) ;
// se sono arrivato alla fine aggiungo l'ultimo punto
if ( ! bFound && ! bLast) {
bLast = true ;
bFound = true ;
}
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
+112
View File
@@ -29,11 +29,24 @@
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkProjectCurveSurf.h"
#include "/EgtDev/Include/EGkOffsetCurve3d.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <future>
using namespace std ;
#define SAVEEXTEND 0
#if SAVEEXTEND
vector<IGeoObj*> vGeo ;
vector<vector<IGeoObj*>> vvGeo ;
#include "/EgtDev/Include/EGkColor.h"
vector<Color> vCol ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
#endif
//-------------------------------------------------------------------------------
// costanti per SurfTmRectSwept
@@ -2135,3 +2148,102 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfExtension( const ISurfTriMesh* pSrfTM, double dExtLen, int nLoop, int nSubCrv, int nType, double dLinTol)
{
// controlli sui parametri in input
if ( pSrfTM == nullptr || nLoop < 0 || nSubCrv < -1)
return nullptr ;
POLYLINEVECTOR vLoops ;
if ( ! pSrfTM->GetLoops( vLoops))
return nullptr ;
PtrOwner<ICurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( ! pLoop->FromPolyLine( vLoops[nLoop]) || nSubCrv >= pLoop->GetCurveCount())
return nullptr ;
// ricavo il tratto di bordo da estendere, con le tangenti della superficie
PtrOwner<ICurve> pEdge ;
if ( nSubCrv == - 1)
pEdge.Set( pLoop) ;
else
pEdge.Set( pLoop->GetCurve( nSubCrv)->Clone()) ;
double dMaxLen = 2.5 ;
PNT5AXVECTOR vPnt5Ax ;
CISURFPVECTOR vSurf ; vSurf.push_back( pSrfTM) ;
bool bClosed = pEdge->IsClosed() ;
ProjectCurveOnSurf( *pEdge, vSurf, dLinTol, dMaxLen, true, vPnt5Ax, false) ;
//PolyLine PL ;
//VCT3DVECTOR vOffDir ;
//bool bClosed = pEdge->IsClosed() ;
/////////// versione con calcolo della tangente
//for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) {
// PL.AddUPoint( i, vPnt5Ax[i].ptP) ;
// Vector3d vtDir ;
// if ( ( i == 0 || i == ssize( vPnt5Ax) - 1) && bClosed)
// vtDir = Media( vPnt5Ax.end()[-1].ptP - vPnt5Ax.end()[-2].ptP, vPnt5Ax[1].ptP - vPnt5Ax[0].ptP) ;
// else if ( i > 0 && i < ssize( vPnt5Ax) - 1)
// vtDir = Media( vPnt5Ax[i].ptP - vPnt5Ax[i-1].ptP, vPnt5Ax[i+1].ptP - vPnt5Ax[i].ptP) ;
// else if ( i < ssize( vPnt5Ax) - 1)
// vtDir = vPnt5Ax[i+1].ptP - vPnt5Ax[i].ptP ;
// else
// vtDir = vPnt5Ax[i].ptP - vPnt5Ax[i-1].ptP ;
// Vector3d& vtN = vPnt5Ax[i].vtDir1 ;
// Vector3d vtOffDir = vtDir ^ vtN ; vtOffDir.Normalize() ;
// vOffDir.push_back( vtOffDir) ;
//}
//////////// qui la tangente è già stata calcolata da ProjectCurveOnSurf
//for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) {
// PL.AddUPoint( i, vPnt5Ax[i].ptP) ;
// vOffDir.push_back( vPnt5Ax[i].vtDir1) ;
//}
OffsetCurve3d off3d ;
if ( ! off3d.Make( vPnt5Ax, dExtLen, nType))
return nullptr ;
PtrOwner<ICurveComposite> pOffEdge( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < off3d.GetCurveCount() ; ++i) {
if ( ! pOffEdge->AddCurve( off3d.GetLongerCurve()))
return nullptr ;
}
#if SAVEEXTEND
vvGeo.clear() ;
vCol.clear() ;
vvGeo.emplace_back() ;
vvGeo.back().push_back( pEdge->Clone()) ;
vvGeo.back().push_back( pOffEdge->Clone()) ;
vCol.push_back( AQUA) ;
vvGeo.emplace_back() ;
for ( int i = 0 ; i < ssize( vOffDir) ; ++i) {
IGeoVector3d* pGV = CreateGeoVector3d() ;
pGV->Set( vOffDir[i] * dExtLen, vPnt5Ax[i].ptP) ;
vvGeo.back().push_back( pGV) ;
}
vCol.push_back( LIME) ;
SaveGeoObj( vvGeo, vCol, "C:\\Temp\\curve offset 3d\\surfExtend_insight.nge") ;
vGeo.clear() ;
vCol.clear() ;
for ( int i = 1 ; i < ssize( vPnt5Ax) ; ++i) {
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( vPnt5Ax[i-1].ptP, vPnt5Ax[i].ptP) ;
vGeo.push_back( pCL) ;
if ( vPnt5Ax[i].nFlag == 6)
vCol.push_back( GREEN) ;
else if ( vPnt5Ax[i].nFlag == 2)
vCol.push_back( RED) ;
else
vCol.push_back( PURPLE) ;
}
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\surfExtend_con-cvx.nge") ;
#endif
PtrOwner<ISurfTriMesh> pSurfExt( GetSurfTriMeshRuled( pEdge, pOffEdge, ISurfTriMesh::RuledType::RLT_MINDIST, dLinTol)) ;
return Release( pSurfExt) ;
}