EgtGeomKernel :

- migliorie alle funzioni SharpRectSwept e BeveledRectSwept
- migliorie varie.
This commit is contained in:
Riccardo Elitropi
2024-05-16 13:06:55 +02:00
parent 3e6aa0d81b
commit c0b5f38301
4 changed files with 388 additions and 188 deletions
+29 -29
View File
@@ -1,4 +1,4 @@
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : PolyLine.cpp Data : 22.12.13 Versione : 1.4l3
@@ -53,7 +53,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
{
// se da aggiungere in coda
if ( bEndOrStart) {
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
++ m_nRejected ;
return true ;
@@ -68,7 +68,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
}
// altrimenti si aggiunge in testa
else {
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
++ m_nRejected ;
return true ;
@@ -92,7 +92,7 @@ PolyLine::Close( void)
// ci devono essere almeno 2 punti
if ( m_lUPoints.size() < 2)
return false ;
// verifico non sia già chiuso
// verifico non sia già chiuso
if ( AreSamePointApprox( m_lUPoints.front().first, m_lUPoints.back().first))
return false ;
// aggiungo un punto uguale al primo in coda
@@ -219,7 +219,7 @@ PolyLine::ToLoc( const Frame3d& frRef)
bool
PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
// se i due riferimenti coincidono, non devo fare alcunché
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
// ciclo sui punti
@@ -233,7 +233,7 @@ PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
bool
PolyLine::Join( PolyLine& PL, double dOffsetPar)
{
// se l'altra polilinea non contiene alcunchè, esco con ok
// se l'altra polilinea non contiene alcunchè, esco con ok
if ( PL.m_lUPoints.size() == 0)
return true ;
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
@@ -385,7 +385,7 @@ PolyLine::GetPrevUPoint( double* pdPar, Point3d* pptP, bool bNotFirst) const
bool
PolyLine::GetCurrUPoint( double* pdPar, Point3d* pptP) const
{
// verifico validità punto corrente
// verifico validità punto corrente
if ( m_iter == m_lUPoints.end())
return false ;
@@ -426,7 +426,7 @@ PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
bool
PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) const
{
// parametro e punto iniziali (è il precedente finale)
// parametro e punto iniziali (è il precedente finale)
if ( m_iter == m_lUPoints.end())
return false ;
if ( pdIni != nullptr)
@@ -510,19 +510,19 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
ptsPCA.AddPoint( Media( ptP1, ptP2, 0.25), dLen / 2) ;
ptsPCA.AddPoint( Media( ptP1, ptP2, 0.75), dLen / 2) ;
}
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
nRank = ptsPCA.GetRank() ;
// se dimensione nulla, o non ci sono punti o sono tutti praticamente coincidenti
if ( nRank == 0)
return ptsPCA.GetCenter( ptCen) ;
// se dimensione 1, allora i punti sono distribuiti su una linea
if ( nRank == 1) {
// assegno il centro e la direzione della linea (il verso è indifferente)
// assegno il centro e la direzione della linea (il verso è indifferente)
ptsPCA.GetCenter( ptCen) ;
ptsPCA.GetPrincipalComponent( 0, vtDir) ;
return true ;
}
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
// Center and normal vector
ptsPCA.GetCenter( ptCen) ;
Vector3d vtX, vtY ;
@@ -530,9 +530,9 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
ptsPCA.GetPrincipalComponent( 1, vtY) ;
vtDir = vtX ^ vtY ;
if ( ! vtDir.Normalize()) {
// riduco la dimensionalità a lineare
// riduco la dimensionalità a lineare
nRank = 1 ;
// assegno il centro e la direzione della linea (il verso è indifferente)
// assegno il centro e la direzione della linea (il verso è indifferente)
ptsPCA.GetCenter( ptCen) ;
vtDir = vtX ;
return true ;
@@ -561,12 +561,12 @@ PolyLine::IsFlat( Plane3d& plPlane, double dToler) const
plPlane.Reset() ;
return false ;
}
// recupero dati sulla planarità della polilinea
// recupero dati sulla planarità della polilinea
int nRank ;
Point3d ptCen ;
Vector3d vtDir ;
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
// imposto il piano a seconda della dimensionalità
// imposto il piano a seconda della dimensionalità
switch ( nRank) {
case 0 : // punto
plPlane.Set( ptCen, Z_AX) ;
@@ -639,13 +639,13 @@ PolyLine::GetAreaXY( double& dArea) const
// verifico sia chiusa
if ( ! IsClosed())
return false ;
// calcolo l'area considerando solo XY (è la Z di Newell)
// calcolo l'area considerando solo XY (è la Z di Newell)
dArea = 0 ;
Point3d ptIni, ptFin ;
for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) {
dArea += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy
}
// considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area
// considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area
// significativa anche se sono coincidenti per le nostre tolleranze
ptIni = ptFin ;
GetFirstPoint( ptFin) ;
@@ -746,7 +746,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
}
}
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
if ( dMaxSqDist > dSqTol) {
// inserisco il punto
@@ -789,7 +789,7 @@ PolyLine::RemoveAlignedPoints( double dToler)
}
// altrimenti chiusa
else {
// cerco il punto più distante dal primo
// cerco il punto più distante dal primo
double dMaxDist = 0. ;
int nMaxInd = 0 ;
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
@@ -966,7 +966,7 @@ PolyLine::MyApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler)
}
}
}
// non è stato eliminato alcunché
// non è stato eliminato alcunché
// ripristino la tolleranza corrente
dCurrToler = dToler ;
// avanzo il terzetto di uno step
@@ -1007,7 +1007,7 @@ PolyLine::MakeConvex( const Vector3d& vtN, bool bLeftSide)
bool
PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
{
// ciclo i controlli finchè non ci sono rimozioni
// ciclo i controlli finchè non ci sono rimozioni
bool bRemoved = true ;
while ( bRemoved) {
bRemoved = false ;
@@ -1035,7 +1035,7 @@ PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
bRemoved = true ;
continue ;
}
// non è stato eliminato alcunché : avanzo il terzetto di uno step
// non è stato eliminato alcunché : avanzo il terzetto di uno step
precP = currP ;
currP = nextP ;
++ nextP ;
@@ -1062,7 +1062,7 @@ PolyLine::Invert( bool bInvertU)
m_lUPoints.reverse() ;
// se richiesto, inverto anche il parametro U
if ( bInvertU) {
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
double dUfin = m_lUPoints.front().second ;
// ciclo su tutti gli elementi
for ( auto& UPoint : m_lUPoints) {
@@ -1277,7 +1277,7 @@ PolyLine::GetMinAreaRectangleXY( Point3d& ptCen, Vector3d& vtAx, double& dLen, d
bool
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
{
// se vuota non faccio alcunché
// se vuota non faccio alcunché
if ( m_lUPoints.size() == 0)
return false ;
@@ -1379,7 +1379,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
return false ;
// Riferimento alla lista dei punti
PNTULIST& List = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
Point3d ptMinDist ;
auto itMinDistEnd = List.end() ;
@@ -1468,7 +1468,7 @@ GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dTol
// assegno nuovo inizio
ptStart = ptEnd ;
}
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
return ( dMinSqDist < dToler * dToler) ;
}
@@ -1481,7 +1481,7 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
return false ;
// Riferimento alla lista dei punti
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
auto itStart = LoopList.begin() ;
@@ -1525,7 +1525,7 @@ SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler,
return false ;
// Riferimento alla lista dei punti
const PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
auto itStart = LoopList.begin() ;
@@ -1608,7 +1608,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
if ( nMinJ < nLastJ)
nMinJ = nLastJ ;
// verifica se è un punto interno in comune con l'altra polyline
// verifica se è un punto interno in comune con l'altra polyline
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
bCommonInternalPoints = true ;
+359 -157
View File
@@ -330,9 +330,11 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
{
// verifico che la linea guida sia piana
Plane3d plGuide ;
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
if ( ! pGuide->IsFlat( plGuide, true, 10 * EPS_SMALL))
return nullptr ;
Vector3d vtNorm = plGuide.GetVersN() ;
Vector3d vtNorm ; pGuide->GetExtrusion( vtNorm) ;
if ( vtNorm.IsSmall())
vtNorm = Z_AX ;
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// curve di offset
@@ -355,7 +357,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
if ( IsNull( pSrfBot))
return nullptr ;
pSrfBot->Translate( -dDimV * vtNorm) ;
pSrfBot->Translate( - dDimV * vtNorm) ;
pSrfBot->Invert() ;
PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ;
if ( IsNull( pSrfRgt))
@@ -407,81 +409,131 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
// step di rotazione per rispettare la tolleranza
double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ;
// aggiungo il cap sull'inizio
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ;
vtStart.Rotate( vtNorm, 0, 1) ;
PolyLine PLStart ;
PLStart.AddUPoint( 0, ptStart) ;
PLStart.AddUPoint( 1, ptStart + dDimH / 2 * vtStart) ;
PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dDimV * vtNorm) ;
PLStart.AddUPoint( 3, ptStart - dDimV * vtNorm) ;
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
return nullptr ;
pSci->Invert() ;
// per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione
for ( int i = 0 ; i < pSci->GetFacetCount() ; ++ i) {
Vector3d vtN ;
// se la faccia ha normale parallela a vtNorm...
if ( pSci->GetFacetNormal( i, vtN) &&
AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) {
// ... ricavo il loop
POLYLINEVECTOR vLoops ;
if ( ! pSci->GetFacetLoops( i, vLoops) || vLoops.empty())
return nullptr ;
// lo semplifico
vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ;
// eseguo triangolazione e aggiungo la faccia alla Soup
PtrOwner<ISurfTriMesh> pStmNewFace( CreateSurfTriMesh()) ;
if ( IsNull( pStmNewFace) ||
! pStmNewFace->CreateByFlatContour( vLoops[0]))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmNewFace) ;
// se l'offset interno alla guida è chiuso
if ( pCrvL->IsClosed()) {
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
Point3d ptRight ; pCrvR->GetEndPoint( ptRight) ;
Point3d ptLeft ; pCrvR->GetStartPoint( ptLeft) ;
Point3d ptJunction ; pCrvL->GetStartPoint( ptJunction) ;
Point3d ptCenter = Media( ptRight, ptLeft) ;
Vector3d vtRight = ptRight - ptCenter ;
Vector3d vtLeft = ptLeft - ptCenter ;
double dAng = ANG_STRAIGHT ;
vtRight.GetAngle( vtLeft, dAng) ;
vtRight.Normalize() ;
PolyLine plLoop ;
// creo il loop defininendo i punti
plLoop.AddUPoint( 0, ptRight) ; // primo punto
double dAngStep = ceil( dAng / dStepRotDeg) ; // aggiusto lo step
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptRight ;
ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ;
plLoop.AddUPoint( i, ptRot) ; // punto intermedio sulla circonferenza
}
// altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli
else
stmSoup.AddSurfTriMesh( *pSci->CloneFacet( i)) ;
plLoop.AddUPoint( dAngStep ++, ptLeft) ; // ultimo punto
plLoop.AddUPoint( dAngStep ++, ptJunction) ; // punto centrale sull'offset chiuso
plLoop.AddUPoint( dAngStep, ptRight) ; // polyLine chiusa
// superificie Top
PtrOwner<ISurfTriMesh> pStmTop( CreateSurfTriMesh()) ;
if ( IsNull( pStmTop) || ! pStmTop->CreateByFlatContour( plLoop))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmTop) ;
// superificie Bottom
PtrOwner<ISurfTriMesh> pStmBottom( CloneSurfTriMesh( pStmTop)) ;
pStmBottom->Translate( - dDimV * vtNorm) ;
pStmBottom->Invert() ;
stmSoup.AddSurfTriMesh( *pStmBottom) ;
// superificie perpendicolare
// la PolyLine che utilizzo la posso ricavare da quella calcolata sopra
plLoop.EraseLastUPoint() ; // apro il loop
plLoop.EraseLastUPoint() ; // tolgo il punto di contatto sull'offset
PtrOwner<ISurfTriMesh> pStmPerp( CreateSurfTriMesh()) ;
if ( IsNull( pStmPerp) || ! pStmPerp->CreateByExtrusion( plLoop, - vtNorm * dDimV) ||
! pStmPerp->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmPerp) ;
}
// aggiungo il cap sulla fine
Point3d ptEnd ;
pGuide->GetEndPoint( ptEnd) ;
Vector3d vtEnd ;
pGuide->GetEndDir( vtEnd) ;
vtEnd.Rotate( vtNorm, 0, -1) ;
PolyLine PLEnd ;
PLEnd.AddUPoint( 0, ptEnd) ;
PLEnd.AddUPoint( 1, ptEnd + dDimH / 2 * vtEnd) ;
PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dDimV * vtNorm) ;
PLEnd.AddUPoint( 3, ptEnd - dDimV * vtNorm) ;
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
return nullptr ;
pSce->Invert() ;
// per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione
for ( int i = 0 ; i < pSce->GetFacetCount() ; ++ i) {
Vector3d vtN ;
// se la faccia ha normale parallela a vtNorm...
if ( pSce->GetFacetNormal( i, vtN) &&
AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) {
// ... ricavo il loop
POLYLINEVECTOR vLoops ;
if ( ! pSce->GetFacetLoops( i, vLoops) || vLoops.empty())
return nullptr ;
// lo semplifico
vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ;
// eseguo triangolazione e aggiungo la faccia alla Soup
PtrOwner<ISurfTriMesh> pStmNewFace( CreateSurfTriMesh()) ;
if ( IsNull( pStmNewFace) ||
! pStmNewFace->CreateByFlatContour( vLoops[0]))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmNewFace) ;
// se l'offset interno della guida è aperto...
else {
// aggiungo il cap sull'inizio
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
Point3d ptSLeft ; pCrvL->GetStartPoint( ptSLeft) ;
Point3d ptSRight ; pCrvR->GetStartPoint( ptSRight) ;
Vector3d vtLeft = ptSLeft - ptStart ;
Vector3d vtRight = ptSRight - ptStart ;
double dAng = ANG_STRAIGHT ;
vtLeft.GetAngle( vtRight, dAng) ;
vtLeft.Normalize() ;
PolyLine plLoop ;
// creo il loop defininendo i punti
plLoop.AddUPoint( 0, ptSLeft) ; // primo punto
double dAngStep = ceil( dAng / dStepRotDeg) ;
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptSLeft ;
ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ;
plLoop.AddUPoint( i, ptRot) ;
}
// altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli
else
stmSoup.AddSurfTriMesh( *pSce->CloneFacet( i)) ;
plLoop.AddUPoint( dAngStep, ptSRight) ; // ultimo punto
plLoop.AddUPoint( dAngStep + 1, ptSLeft) ; // polyline chiusa
// creo la superficie Top
PtrOwner<ISurfTriMesh> pStmTop_start( CreateSurfTriMesh()) ;
if ( IsNull( pStmTop_start) || ! pStmTop_start->CreateByFlatContour( plLoop))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmTop_start) ;
// superificie Bottom
PtrOwner<ISurfTriMesh> pStmBottom_start( CloneSurfTriMesh( pStmTop_start)) ;
pStmBottom_start->Translate( - dDimV * vtNorm) ;
pStmBottom_start->Invert() ;
stmSoup.AddSurfTriMesh( *pStmBottom_start) ;
// superificie perpendicolare
// la PolyLine che utilizzo la posso ricavare da quella calcolata sopra
plLoop.EraseLastUPoint() ; // apro il loop
PtrOwner<ISurfTriMesh> pStmPerp_start( CreateSurfTriMesh()) ;
if ( IsNull( pStmPerp_start) || ! pStmPerp_start->CreateByExtrusion( plLoop, - vtNorm * dDimV) ||
! pStmPerp_start->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmPerp_start) ;
// aggiungo il cap sulla fine
Point3d ptEnd ;
pGuide->GetEndPoint( ptEnd) ;
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
pCrvL->GetEndPoint( ptSLeft) ;
pCrvR->GetEndPoint( ptSRight) ;
vtLeft = ptSLeft - ptEnd ;
vtRight = ptSRight - ptEnd ;
dAng = ANG_STRAIGHT ;
vtRight.GetAngle( vtLeft, dAng) ;
vtRight.Normalize() ;
plLoop.Clear() ;
// creo il loop defininendo i punti
plLoop.AddUPoint( 0, ptSRight) ;
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptSRight ;
ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ;
plLoop.AddUPoint( i, ptRot) ;
}
plLoop.AddUPoint( dAngStep, ptSLeft) ; // ultimo punto
plLoop.AddUPoint( dAngStep + 1, ptSRight) ; // polyline chiusa
// creo la superficie Top
PtrOwner<ISurfTriMesh> pStmTop_end( CreateSurfTriMesh()) ;
if ( IsNull( pStmTop_end) || ! pStmTop_end->CreateByFlatContour( plLoop))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmTop_end) ;
// creo la superificie Bottom
PtrOwner<ISurfTriMesh> pStmBottom_end( CloneSurfTriMesh( pStmTop_end)) ;
pStmBottom_end->Translate( - dDimV * vtNorm) ;
pStmBottom_end->Invert() ;
stmSoup.AddSurfTriMesh( *pStmBottom_end) ;
// creo la superificie perpendicolare alla guida
plLoop.EraseLastUPoint() ; // apro il loop
PtrOwner<ISurfTriMesh> pStmPerp_end( CreateSurfTriMesh()) ;
if ( IsNull( pStmPerp_end) || ! pStmPerp_end->CreateByExtrusion( plLoop, - vtNorm * dDimV) ||
! pStmPerp_end->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmPerp_end) ;
}
// completo unione e recupero la superficie risultante
if ( ! stmSoup.End())
@@ -509,13 +561,13 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
// verifico che la linea guida sia piana
Plane3d plGuide ;
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
if ( ! pGuide->IsFlat( plGuide, true, 10 * EPS_SMALL))
return nullptr ;
// assegno la normale del piano
Vector3d vtNorm = plGuide.GetVersN() ;
Vector3d vtNorm ; pGuide->GetExtrusion( vtNorm) ;
if ( vtNorm.IsSmall())
vtNorm = Z_AX ;
// determino il punto centrale della sezione
Point3d ptCen ;
pGuide->GetStartPoint( ptCen) ;
Point3d ptCen ; pGuide->GetStartPoint( ptCen) ;
ptCen -= dDimV / 2 * vtNorm ;
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
@@ -544,7 +596,6 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i)
bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ;
}
if ( ! bOk ||
vOffsCrv[0].GetCurveCount() == 0 || vOffsCrv[1].GetCurveCount() == 0 ||
vOffsCrv[2].GetCurveCount() == 0 || vOffsCrv[3].GetCurveCount() == 0)
@@ -640,85 +691,235 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
else if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
// step di rotazione per rispettare il tipo o la tolleranza
double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ;
// aggiungo il cap sull'inizio
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ;
vtStart.Rotate( vtNorm, 0, 1) ;
PolyLine PLStart ;
PLStart.AddUPoint( 0, ptStart) ;
PLStart.AddUPoint( 1, ptStart + ( dDimH / 2 - dBevelH) * vtStart) ;
PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dBevelV * vtNorm) ;
PLStart.AddUPoint( 3, ptStart + dDimH / 2 * vtStart - ( dDimV - dBevelV) * vtNorm) ;
PLStart.AddUPoint( 4, ptStart + ( dDimH / 2 - dBevelH) * vtStart - dDimV * vtNorm) ;
PLStart.AddUPoint( 5, ptStart - dDimV * vtNorm) ;
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
return nullptr ;
pSci->Invert() ;
// per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione
for ( int i = 0 ; i < pSci->GetFacetCount() ; ++ i) {
Vector3d vtN ;
// se la faccia ha normale parallela a vtNorm...
if ( pSci->GetFacetNormal( i, vtN) &&
AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) {
// ... ricavo il loop
POLYLINEVECTOR vLoops ;
if ( ! pSci->GetFacetLoops( i, vLoops) || vLoops.empty())
return nullptr ;
// lo semplifico
vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ;
// eseguo triangolazione e aggiungo la faccia alla Soup
PtrOwner<ISurfTriMesh> pStmNewFace( CreateSurfTriMesh()) ;
if ( IsNull( pStmNewFace) ||
! pStmNewFace->CreateByFlatContour( vLoops[0]))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmNewFace) ;
// se l'offset interno della guida è chiuso...
if ( pCrvL->IsClosed()) {
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
Point3d ptRight ; pCrvR->GetEndPoint( ptRight) ;
Point3d ptLeft ; pCrvR->GetStartPoint( ptLeft) ;
Point3d ptJunction ; pCrvL->GetStartPoint( ptJunction) ;
Point3d ptCenter = Media( ptRight, ptLeft) ;
Vector3d vtRight = ptRight - ptCenter ;
Vector3d vtLeft = ptLeft - ptCenter ;
double dAng = ANG_STRAIGHT ;
vtRight.GetAngle( vtLeft, dAng) ;
vtRight.Normalize() ;
PolyLine plLoop ;
// creo il loop defininendo i punti
plLoop.AddUPoint( 0, ptRight) ; // primo punto
double dAngStep = ceil( dAng / dStepRotDeg) ; // aggiusto lo step
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptRight ;
ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ;
plLoop.AddUPoint( i, ptRot) ; // punto intermedio sulla circonferenza
}
// altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli
else
stmSoup.AddSurfTriMesh( *pSci->CloneFacet( i)) ;
plLoop.AddUPoint( dAngStep ++, ptLeft) ; // ultimo punto
plLoop.AddUPoint( dAngStep ++, ptJunction) ; // punto centrale sull'offset chiuso
plLoop.AddUPoint( dAngStep, ptRight) ; // polyLine chiusa
// superificie Top
PtrOwner<ISurfTriMesh> pStmTop( CreateSurfTriMesh()) ;
if ( IsNull( pStmTop) || ! pStmTop->CreateByFlatContour( plLoop))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmTop) ;
// superificie Bottom
PtrOwner<ISurfTriMesh> pStmBottom( CloneSurfTriMesh( pStmTop)) ;
if ( IsNull( pStmBottom) || ! pStmBottom->Mirror( ptCen, vtNorm))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmBottom) ;
// calcolo l'angolo di rotazione per la faccia Top del bevel
// NB. Questo angolo va ricalcolato, il bevel è inclinato rispetto alla normale della guida
ptCenter.Translate( - dBevelV * vtNorm) ;
Point3d ptbRight ; pCrvRb->GetEndPoint( ptbRight) ;
Point3d ptbLeft ; pCrvRb->GetStartPoint( ptbLeft) ;
Vector3d vtbLeft = ptbLeft - ptCenter ;
Vector3d vtbRight = ptbRight - ptCenter ;
dAng = ANG_STRAIGHT ;
vtbRight.GetAngle( vtbLeft, dAng) ;
vtbRight.Normalize() ;
// la PolyLine che utilizzo la posso ricavare da quella calcolata sopra
plLoop.EraseLastUPoint() ; // apro il loop
plLoop.EraseLastUPoint() ; // tolgo il punto di contatto sull'offset
// creo il loop defininendo i punti
PolyLine plLoopB ;
plLoopB.AddUPoint( 0, ptbRight) ;
dAngStep = ceil( dAng / dStepRotDeg) ;
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptbRight ;
ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ;
plLoopB.AddUPoint( i, ptRot) ;
}
plLoopB.AddUPoint( dAngStep, ptbLeft) ;
// creo la superficie Top Bevel
PtrOwner<ISurfTriMesh> pStmbTop_start( CreateSurfTriMesh()) ;
if ( IsNull( pStmbTop_start) ||
! pStmbTop_start->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) ||
! pStmbTop_start->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmbTop_start) ;
// creo la superificie Bottom Bevel
PtrOwner<ISurfTriMesh> pStmbBottom_start( CloneSurfTriMesh( pStmbTop_start)) ;
if ( IsNull( pStmbBottom_start) || ! pStmbBottom_start->Mirror( ptCen, vtNorm))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmbBottom_start) ;
// creo la superficie perpendicolare alla guida
PolyLine plLoopB1 = plLoopB ;
plLoopB1.Mirror( ptCen, vtNorm) ;
PtrOwner<ISurfTriMesh> pStmPerp( CreateSurfTriMesh()) ;
if ( IsNull( pStmPerp) ||
! pStmPerp->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) ||
! pStmPerp->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmPerp) ;
}
// aggiungo il cap sulla fine
Point3d ptEnd ;
pGuide->GetEndPoint( ptEnd) ;
Vector3d vtEnd ;
pGuide->GetEndDir( vtEnd) ;
vtEnd.Rotate( vtNorm, 0, -1) ;
PolyLine PLEnd ;
PLEnd.AddUPoint( 0, ptEnd) ;
PLEnd.AddUPoint( 1, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd) ;
PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dBevelV * vtNorm) ;
PLEnd.AddUPoint( 3, ptEnd + dDimH / 2 * vtEnd - ( dDimV - dBevelV) * vtNorm) ;
PLEnd.AddUPoint( 4, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd - dDimV * vtNorm) ;
PLEnd.AddUPoint( 5, ptEnd - dDimV * vtNorm) ;
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
return nullptr ;
pSce->Invert() ;
// per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione
for ( int i = 0 ; i < pSce->GetFacetCount() ; ++ i) {
Vector3d vtN ;
// se la faccia ha normale parallela a vtNorm...
if ( pSce->GetFacetNormal( i, vtN) &&
AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) {
// ... ricavo il loop
POLYLINEVECTOR vLoops ;
if ( ! pSce->GetFacetLoops( i, vLoops) || vLoops.empty())
return nullptr ;
// lo semplifico
vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ;
// eseguo triangolazione e aggiungo la faccia alla Soup
PtrOwner<ISurfTriMesh> pStmNewFace( CreateSurfTriMesh()) ;
if ( IsNull( pStmNewFace) ||
! pStmNewFace->CreateByFlatContour( vLoops[0]))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmNewFace) ;
// se l'offset interno della guida è aperto...
else {
// aggiungo il cap sull'inizio
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
Point3d ptSLeft ; pCrvL->GetStartPoint( ptSLeft) ;
Point3d ptSRight ; pCrvR->GetStartPoint( ptSRight) ;
Vector3d vtLeft = ptSLeft - ptStart ;
Vector3d vtRight = ptSRight - ptStart ;
double dAng = ANG_STRAIGHT ;
vtLeft.GetAngle( vtRight, dAng) ;
vtLeft.Normalize() ;
PolyLine plLoop ;
// creo il loop defininendo i punti
plLoop.AddUPoint( 0, ptSLeft) ; // primo punto
double dAngStep = ceil( dAng / dStepRotDeg) ;
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptSLeft ;
ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ;
plLoop.AddUPoint( i, ptRot) ;
}
// altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli
else
stmSoup.AddSurfTriMesh( *pSce->CloneFacet( i)) ;
plLoop.AddUPoint( dAngStep, ptSRight) ; // ultimo punto
plLoop.AddUPoint( dAngStep + 1, ptSLeft) ; // polyline chiusa
// creo la superficie Top
PtrOwner<ISurfTriMesh> pStmTop_start( CreateSurfTriMesh()) ;
if ( IsNull( pStmTop_start) || ! pStmTop_start->CreateByFlatContour( plLoop))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmTop_start) ;
// creo la superificie Bottom
PtrOwner<ISurfTriMesh> pStmBottom_start( CloneSurfTriMesh( pStmTop_start)) ;
if ( IsNull( pStmBottom_start) || ! pStmBottom_start->Mirror( ptCen, vtNorm))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmBottom_start) ;
// calcolo l'angolo di rotazione per la faccia Top del bevel
ptStart.Translate( - dBevelV * vtNorm) ;
Point3d ptSbLeft ; pCrvLb->GetStartPoint( ptSbLeft) ;
Point3d ptSbRight ; pCrvRb->GetStartPoint( ptSbRight) ;
Vector3d vtbLeft = ptSbLeft - ptStart ;
Vector3d vtbRight = ptSbRight - ptStart ;
dAng = ANG_STRAIGHT ;
vtbLeft.GetAngle( vtbRight, dAng) ;
vtbLeft.Normalize() ;
plLoop.EraseLastUPoint() ; // apro il loop
// creo il loop defininendo i punti
PolyLine plLoopB ;
plLoopB.AddUPoint( 0, ptSbLeft) ;
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptSbLeft ;
ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ;
plLoopB.AddUPoint( i, ptRot) ;
}
plLoopB.AddUPoint( dAngStep, ptSbRight) ; // ultimo punto
// creo la superficie Top Bevel
PtrOwner<ISurfTriMesh> pStmbTop_start( CreateSurfTriMesh()) ;
if ( IsNull( pStmbTop_start) ||
! pStmbTop_start->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) ||
! pStmbTop_start->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmbTop_start) ;
// creo la superificie Bottom Bevel
PtrOwner<ISurfTriMesh> pStmbBottom_start( CloneSurfTriMesh( pStmbTop_start)) ;
if ( IsNull( pStmbBottom_start) || ! pStmbBottom_start->Mirror( ptCen, vtNorm))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmbBottom_start) ;
// creo la superficie perpendicolare alla guida
PolyLine plLoopB1 = plLoopB ;
plLoopB1.Mirror( ptCen, vtNorm) ;
PtrOwner<ISurfTriMesh> pStmPerp_start( CreateSurfTriMesh()) ;
if ( IsNull( pStmPerp_start) ||
! pStmPerp_start->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) ||
! pStmPerp_start->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmPerp_start) ;
// aggiungo il cap sulla fine
Point3d ptEnd ;
pGuide->GetEndPoint( ptEnd) ;
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
pCrvL->GetEndPoint( ptSLeft) ;
pCrvR->GetEndPoint( ptSRight) ;
vtLeft = ptSLeft - ptEnd ;
vtRight = ptSRight - ptEnd ;
dAng = ANG_STRAIGHT ;
vtRight.GetAngle( vtLeft, dAng) ;
vtRight.Normalize() ;
plLoop.Clear() ;
// creo il loop defininendo i punti
plLoop.AddUPoint( 0, ptSRight) ;
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptSRight ;
ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ;
plLoop.AddUPoint( i, ptRot) ;
}
plLoop.AddUPoint( dAngStep, ptSLeft) ; // ultimo punto
plLoop.AddUPoint( dAngStep + 1, ptSRight) ; // polyline chiusa
// creo la superficie Top
PtrOwner<ISurfTriMesh> pStmTop_end( CreateSurfTriMesh()) ;
if ( IsNull( pStmTop_end) || ! pStmTop_end->CreateByFlatContour( plLoop))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmTop_end) ;
// creo la superificie Bottom
PtrOwner<ISurfTriMesh> pStmBottom_end( CreateSurfTriMesh()) ;
if ( IsNull( pStmBottom_end) ||
! pStmBottom_end->CopyFrom( pStmTop_end) ||
! pStmBottom_end->Mirror( ptCen, vtNorm))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmBottom_end) ;
// calcolo l'angolo di rotazione per la faccia Top del bevel
ptEnd.Translate( - dBevelV * vtNorm) ;
pCrvLb->GetEndPoint( ptSbLeft) ;
pCrvRb->GetEndPoint( ptSbRight) ;
vtbLeft = ptSbLeft - ptEnd ;
vtbRight = ptSbRight - ptEnd ;
dAng = ANG_STRAIGHT ;
vtbRight.GetAngle( vtbLeft, dAng) ;
vtbRight.Normalize() ;
plLoop.EraseLastUPoint() ; // apro il loop
// creo il loop defininendo i punti
plLoopB.Clear() ;
plLoopB.AddUPoint( 0, ptSbRight) ;
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
for ( int i = 1 ; i < dAngStep ; ++ i) {
Point3d ptRot = ptSbRight ;
ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ;
plLoopB.AddUPoint( i, ptRot) ;
}
plLoopB.AddUPoint( dAngStep, ptSbLeft) ; // ultimo punto
// creo la superficie Top Bevel
PtrOwner<ISurfTriMesh> pStmbTop_end( CreateSurfTriMesh()) ;
if ( IsNull( pStmbTop_end) ||
! pStmbTop_end->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) ||
! pStmbTop_end->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmbTop_end) ;
// creo la superificie Bottom Bevel
PtrOwner<ISurfTriMesh> pStmbBottom_end( CloneSurfTriMesh( pStmbTop_end)) ;
if ( IsNull( pStmbBottom_end) || ! pStmbBottom_end->Mirror( ptCen, vtNorm))
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmbBottom_end) ;
// creo la superficie perpendicolare alla guida
plLoopB1 = plLoopB ;
plLoopB1.Mirror( ptCen, vtNorm) ;
PtrOwner<ISurfTriMesh> pStmPerp_end( CreateSurfTriMesh()) ;
if ( IsNull( pStmPerp_end) ||
! pStmPerp_end->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) ||
! pStmPerp_end->Invert())
return nullptr ;
stmSoup.AddSurfTriMesh( *pStmPerp_end) ;
}
// completo unione e recupero la superficie risultante
if ( ! stmSoup.End())
@@ -738,6 +939,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol)
-1
View File
@@ -26,7 +26,6 @@
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include <thread>
#include <future>
-1
View File
@@ -647,7 +647,6 @@ VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const
}
int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide
int nPos = j * m_nNx[nMap] + i ; // posizione del dexel corrente
bool bInside = false ; // Flag entrata/uscita per tratto di retta
Point3d ptIn ; Vector3d vtInN ;