EgtGeomKernel 2.4c1 :

- migliorato calcolo distanza minima tra due linee
- eliminate da Trimesh parti inutili
- in Trimesh calcolo Loop di una faccia risolto problema di ciclo infinito
- in Trimesh aggiunta funzione per eliminare triangoli esattamente sovrapposti.
This commit is contained in:
DarioS
2022-03-14 09:03:13 +01:00
parent de34cfb7e8
commit f353e65e61
10 changed files with 251 additions and 2241 deletions
+5 -5
View File
@@ -109,7 +109,7 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB)
DistLineLine LineLineDistCalc( ptStA, PtEnA, ptStB, PtEnB) ;
double dSqSegSegDist ;
LineLineDistCalc.GetSqDist( dSqSegSegDist) ;
if ( dSqSegSegDist < EPS_SMALL * EPS_SMALL)
if ( dSqSegSegDist < SQ_EPS_SMALL)
return true ;
}
}
@@ -136,14 +136,14 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB)
vtSegFirstA /= dSegLenFirstA ;
DistLineLine LineLineDistCalcFirstA( ptLineP, vtLineV, 100., trTriaA.GetP( nFirstMaxPosA), vtSegFirstA, dSegLenFirstA, false) ;
double dIntParStA, dOtherParFirstA ;
LineLineDistCalcFirstA.GetParamsAtMinDistPoints( dIntParStA, dOtherParFirstA) ;
LineLineDistCalcFirstA.GetPositionsAtMinDistPoints( dIntParStA, dOtherParFirstA) ;
// Limito la retta col secondo segmento trovato di A
Vector3d vtSegSecondA = trTriaA.GetP( ( nSecondMaxPosA + 1) % 3) - trTriaA.GetP( nSecondMaxPosA) ;
double dSegLenSecondA = vtSegSecondA.Len() ;
vtSegSecondA /= dSegLenSecondA ;
DistLineLine LineLineDistCalcSecondA( ptLineP, vtLineV, 100., trTriaA.GetP( nSecondMaxPosA), vtSegSecondA, dSegLenSecondA, false) ;
double dIntParEnA, dOtherParSecondA ;
LineLineDistCalcSecondA.GetParamsAtMinDistPoints( dIntParEnA, dOtherParSecondA) ;
LineLineDistCalcSecondA.GetPositionsAtMinDistPoints( dIntParEnA, dOtherParSecondA) ;
// Ordino i parametri lungo la retta di intersezione fra i piani
if ( dIntParStA > dIntParEnA) {
swap( dIntParStA, dIntParEnA) ;
@@ -163,14 +163,14 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB)
vtSegFirstB /= dSegLenFirstB ;
DistLineLine LineLineDistCalcFirstB( ptLineP, vtLineV, 100., trTriaB.GetP( nFirstMaxPosB), vtSegFirstB, dSegLenFirstB, false) ;
double dIntParStB, dOtherParFirstB ;
LineLineDistCalcFirstB.GetParamsAtMinDistPoints( dIntParStB, dOtherParFirstB) ;
LineLineDistCalcFirstB.GetPositionsAtMinDistPoints( dIntParStB, dOtherParFirstB) ;
// Limito la retta col secondo segmento trovato di B
Vector3d vtSegSecondB = trTriaB.GetP( ( nSecondMaxPosB + 1) % 3) - trTriaB.GetP( nSecondMaxPosB) ;
double dSegLenSecondB = vtSegSecondB.Len() ;
vtSegSecondB /= dSegLenSecondB ;
DistLineLine LineLineDistCalcSecondB( ptLineP, vtLineV, 100., trTriaB.GetP( nSecondMaxPosA), vtSegSecondB, dSegLenSecondB, false) ;
double dIntParEnB, dOtherParSecondB ;
LineLineDistCalcSecondB.GetParamsAtMinDistPoints( dIntParEnB, dOtherParSecondB) ;
LineLineDistCalcSecondB.GetPositionsAtMinDistPoints( dIntParEnB, dOtherParSecondB) ;
// Ordino i parametri lungo la retta di intersezione fra i piani
if ( dIntParStB > dIntParEnB) {
swap( dIntParStB, dIntParEnB) ;
+84 -84
View File
@@ -18,6 +18,8 @@
#include "/EgtDev/Include/EGkGeoConst.h"
#include <algorithm>
using namespace std ;
//----------------------------------------------------------------------------
DistLineLine::DistLineLine( const Point3d& ptSt1, const Point3d& ptEn1,
const Point3d& ptSt2, const Point3d& ptEn2,
@@ -57,6 +59,7 @@ DistLineLine::GetSqDist( double& dSqDist)
{
if ( m_dSqDist < 0)
return false ;
dSqDist = m_dSqDist ;
return true ;
}
@@ -67,7 +70,10 @@ DistLineLine::GetDist( double& dDist)
{
if ( m_dSqDist < 0)
return false ;
dDist = sqrt( m_dSqDist) ;
if ( m_dDist < 0)
m_dDist = sqrt( m_dSqDist) ;
dDist = m_dDist ;
return true ;
}
@@ -84,55 +90,48 @@ DistLineLine::GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2)
//----------------------------------------------------------------------------
bool
DistLineLine::GetParamsAtMinDistPoints( double& dPar1, double& dPar2)
DistLineLine::GetPositionsAtMinDistPoints( double& dPos1, double& dPos2)
{
if ( m_dSqDist < 0)
return false ;
dPar1 = m_dPar1 ;
dPar2 = m_dPar2 ;
dPos1 = m_dPos1 ;
dPos2 = m_dPos2 ;
return true ;
}
//----------------------------------------------------------------------------
// Calcola la distanza fra i due elemnti lineari, i punti di minima distanza e
// i loro rispettivi parametri.
// Se la coppia di punti di minima distanza non è unica ne viene scelta una
// in base a comodità di calcolo.
// Calcola la distanza fra i due elementi lineari, i punti di minima distanza e le loro posizioni.
// Se i due elementi sono paralleli i punti di minimo sono scelti secondo convenienza.
void
DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
bool bIsSegment1, bool bIsSegment2)
{
// Caso di elementi lineari paralleli/antiparalleli
// Se elementi paralleli o antiparalleli
if ( AreSameOrOppositeVectorExact( vtD1, vtD2)) {
// Almeno un elemento è una retta
if ( ! ( bIsSegment1 && bIsSegment2)) {
// Il primo elemento è segmento, quindi deve essere una retta il secondo
if ( bIsSegment1) {
Vector3d vtStSt = ptSt1 - ptSt2 ;
double dLong = vtStSt * vtD2 ;
Vector3d vtDist = vtStSt - dLong * vtD2 ;
m_dSqDist = vtDist.SqLen() ;
m_dDist = sqrt( m_dSqDist) ;
m_dPar1 = 0 ;
m_dPar2 = dLong ;
m_ptMinDist1 = ptSt1 ;
m_ptMinDist2 = ptSt2 + dLong * vtD2 ;
}
// Il primo elemento è una retta
else {
Vector3d vtStSt = ptSt2 - ptSt1 ;
double dLong = vtStSt * vtD1 ;
Vector3d vtDist = vtStSt - dLong * vtD1 ;
m_dSqDist = vtDist.SqLen() ;
m_dDist = sqrt( m_dSqDist) ;
m_dPar1 = dLong ;
m_dPar2 = 0 ;
m_ptMinDist1 = ptSt1 + dLong * vtD1 ;
m_ptMinDist2 = ptSt2 ;
}
// Se il primo elemento è una retta infinita
if ( ! bIsSegment1) {
Vector3d vtStSt = ptSt2 - ptSt1 ;
double dLong = vtStSt * vtD1 ;
Vector3d vtDist = vtStSt - dLong * vtD1 ;
m_dSqDist = vtDist.SqLen() ;
m_dPos1 = dLong ;
m_dPos2 = 0 ;
m_ptMinDist1 = ptSt1 + dLong * vtD1 ;
m_ptMinDist2 = ptSt2 ;
}
// se altrimenti il secondo elemento è una retta infinita
else if ( ! bIsSegment2) {
Vector3d vtStSt = ptSt1 - ptSt2 ;
double dLong = vtStSt * vtD2 ;
Vector3d vtDist = vtStSt - dLong * vtD2 ;
m_dSqDist = vtDist.SqLen() ;
m_dPos1 = 0 ;
m_dPos2 = dLong ;
m_ptMinDist1 = ptSt1 ;
m_ptMinDist2 = ptSt2 + dLong * vtD2 ;
}
// Entrambi gli elementi sono segmenti
// altrimenti entrambi gli elementi sono segmenti
else {
Point3d ptEn1 = ptSt1 + dLen1 * vtD1 ;
Point3d ptEn2 = ptSt2 + dLen2 * vtD2 ;
@@ -140,7 +139,7 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen
Vector3d vtStEn = ptEn2 - ptSt1 ;
double dStU = vtStSt * vtD1 ;
double dEnU = vtStEn * vtD1 ;
// Classifico i punti del segmento segmento in base alla loro
// Classifico i punti del secondo segmento in base alla loro
// coordinata rispetto all'ordinamento generato dal primo.
double dMinPar, dMaxPar ;
Point3d ptMinPar, ptMaxPar ;
@@ -159,70 +158,71 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen
// Possibili posizioni reciproche dei segmenti
if ( dMinPar > dLen1) {
m_dSqDist = SqDist( ptEn1, ptMinPar) ;
m_dDist = sqrt( m_dSqDist) ;
m_ptMinDist1 = ptEn1 ;
m_ptMinDist2 = ptMinPar ;
m_dPar1 = dLen1 ;
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
m_dPos1 = dLen1 ;
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
}
else if ( dMinPar > 0) {
m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ;
m_dDist = sqrt( m_dSqDist) ;
m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ;
m_ptMinDist1 = ptSt1 + dMinPar * vtD1 ;
m_ptMinDist2 = ptMinPar ;
m_dPar1 = dMinPar ;
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
m_dPos1 = dMinPar ;
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
}
else if ( dMaxPar > 0) {
m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ;
m_dDist = sqrt( m_dSqDist) ;
m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ;
m_ptMinDist1 = ptSt1 ;
m_ptMinDist2 = ptSt2 + ( ptSt1 - ptSt2) * vtD2 * vtD2 ;
m_dPar1 = 0 ;
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
m_dPos1 = 0 ;
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
}
else {
m_dSqDist = SqDist( ptSt1, ptMaxPar) ;
m_dDist = sqrt( m_dSqDist) ;
m_ptMinDist1 = ptSt1 ;
m_ptMinDist2 = ptMaxPar ;
m_dPar1 = 0 ;
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
m_dPos1 = 0 ;
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
}
}
return ;
}
// Caso generale
Vector3d vtDist0 = ptSt2 - ptSt1 ;
double dDist01 = vtDist0 * vtD1 ;
double dDist02 = vtDist0 * vtD2 ;
double dDotD1D2 = vtD1 * vtD2 ;
double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ;
double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
double dMin1 = - INFINITO ;
double dMax1 = INFINITO ;
double dMin2 = - INFINITO ;
double dMax2 = INFINITO ;
double dSt1On2 = ( ptSt1 - ptSt2) * vtD2 ;
double dEn1On2 = ( ptSt1 + dLen1 * vtD1 - ptSt2) * vtD2 ;
if ( bIsSegment1) {
dMin1 = 0 ;
dMax1 = dLen1 ;
dMin2 = std::min( dSt1On2, dEn1On2) ;
dMax2 = std::max( dSt1On2, dEn1On2) ;
else {
// Posizioni a distanza minima tra rette illimitate
Vector3d vtStSt = ptSt2 - ptSt1 ;
double dDist01 = vtStSt * vtD1 ;
double dDist02 = vtStSt * vtD2 ;
double dDotD1D2 = vtD1 * vtD2 ;
double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ;
double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
// Posizioni minime e massime sui segmenti
double dMin1 = ( bIsSegment1 ? 0 : -INFINITO) ;
double dMax1 = ( bIsSegment1 ? dLen1 : INFINITO) ;
double dMin2 = ( bIsSegment2 ? 0 : -INFINITO) ;
double dMax2 = ( bIsSegment2 ? dLen2 : INFINITO) ;
// Se entrambe le posizioni stanno nei segmenti
if ( dT1 >= dMin1 && dT1 <= dMax1 && dT2 >= dMin2 && dT2 <= dMax2) {
m_dPos1 = dT1 ;
m_dPos2 = dT2 ;
}
// se altrimenti solo la prima sta nel segmento
else if ( dT1 >= dMin1 && dT1 <= dMax1) {
m_dPos2 = Clamp( dT2, dMin2, dMax2) ;
m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ;
}
// se altrimenti solo la seconda sta nel segmento
else if ( dT2 >= dMin2 && dT2 <= dMax2) {
m_dPos1 = Clamp( dT1, dMin1, dMax1) ;
m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ;
}
// altrimenti nessuna sta nel suo segmento
else {
m_dPos1 = Clamp( dT1, dMin1, dMax1) ;
m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ;
m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ;
}
m_ptMinDist1 = ptSt1 + m_dPos1 * vtD1 ;
m_ptMinDist2 = ptSt2 + m_dPos2 * vtD2 ;
m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ;
}
if ( bIsSegment2) {
double dSt2On1 = ( ptSt2 - ptSt1) * vtD1 ;
double dEn2On1 = ( ptSt2 + dLen2 * vtD2 - ptSt1) * vtD1 ;
dMin1 = std::max( dMin1, std::min( dSt2On1, dEn2On1)) ;
dMax1 = std::min( dMax1, std::max( dSt2On1, dEn2On1)) ;
dMin2 = std::max( dMin2, 0.) ;
dMax2 = std::min( dMax2, dLen2) ;
}
m_dPar1 = Clamp( dT1, dMin1, dMax1) ;
m_dPar2 = Clamp( dT2, dMin2, dMax2) ;
m_ptMinDist1 = ptSt1 + m_dPar1 * vtD1 ;
m_ptMinDist2 = ptSt2 + m_dPar2 * vtD2 ;
m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ;
m_dDist = sqrt( m_dSqDist) ;
}
}
+4 -4
View File
@@ -37,17 +37,17 @@ class DistLineLine
bool IsSmall( void) { return IsEpsilon( EPS_SMALL) ; }
bool IsZero( void) { return IsEpsilon( EPS_ZERO) ; }
bool GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2) ;
bool GetParamsAtMinDistPoints( double& dPar1, double& dPar2) ;
bool GetPositionsAtMinDistPoints( double& dPos1, double& dPos2) ;
private :
void Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
bool bIsSegment1 = true, bool bIsSegment2 = true) ;
bool bIsSegment1, bool bIsSegment2) ;
private:
double m_dSqDist ;
double m_dDist ;
double m_dPar1 ;
double m_dPar2 ;
double m_dPos1 ;
double m_dPos2 ;
Point3d m_ptMinDist1 ;
Point3d m_ptMinDist2 ;
} ;
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -3180,7 +3180,7 @@ bool
SurfTriMesh::InvertTriangle( int nT)
{
// controllo validità triangolo
if ( m_vTria[nT].nIdVert[0] == SVT_DEL)
if ( ! ExistsTriangle( nT))
return true ;
// scambio di due vertici
swap( m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]) ;
+4 -22
View File
@@ -310,6 +310,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error")
return *this ; }
bool Clear( void) ;
bool ExistsTriangle( int nT) const
{ return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; }
bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ;
bool GetTriangleFlag( int nId, int& nFlag) const ;
bool GetTriangleTempInt( int nId, int& nTempInt) const ;
@@ -364,33 +366,13 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool VerifyConnection( void) const ;
bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ;
bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ;
bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ;
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
int VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) ;
int IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
bool IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA,
const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB,
LineFacetClassVector& IntersLinePart) ;
bool IntersectTriMeshFacets( SurfTriMesh& Other) ;
bool RetriangulateFacetPieces( const PieceMap& NewFacet,
const INTERSEDGEMAP& EdgeInterLineMap,
const INTERSEDGEMAP& EdgeEdgeLineMap) ;
bool EdgeInteriorContactManager( const SurfTriMesh& OthSurf,
const INTERSCHAINMAP& InterInterLineMap,
const INTERSEDGEMAP& EdgeInterLineMap) ;
bool EdgeEdgeContactManager( const SurfTriMesh& OthSurf,
const INTERSCHAINMAP& InterInterLineMap,
const INTERSEDGEMAP& EdgeEdgeLineMap) ;
bool SplitFacet( const INTERSCHAINMAP& IntersLineMap, PieceMap& NewFacet);
bool IdentifyParts( void) const ;
bool RemoveTJunctions( void) ;
bool RemoveCaps( void) ;
bool RemoveTripleTriangles( void) ;
bool ScanForTripleTriangles( bool& bModified) ;
bool RemoveDoubleTriangles( bool& bModified) ;
bool RemoveTJunctions( bool& bModified) ;
bool FlipTriangles( int nTA, int nTB) ;
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ;
bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ;
+45 -2028
View File
File diff suppressed because it is too large Load Diff
+3 -90
View File
@@ -40,13 +40,10 @@ SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
int nTriaOriCnt = GetTriangleCount() ;
int nFacetOriCnt = GetFacetCount() ;
// eseguo il taglio con il metodo delle faccette o dei triangoli (per ora solo coi triangoli)
// eseguo il taglio con il metodo dei triangoli
bool bModif = false ;
if ( true || ! CutByFacets( plPlane, bSaveOnEq, bModif)) {
bModif = false ;
if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif))
return false ;
}
if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif))
return false ;
// se effettuate modifiche
if ( bModif) {
@@ -282,90 +279,6 @@ SurfTriMesh::CutTriangleByPlane( int nT, const Plane3d& plPlane, bool bSaveOnEq,
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// Setto posizione triangoli non definita
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT)
m_vTria[nT].nTempPart = 0 ;
INTERSCHAINMAP IntersLineMap ;
// Ciclo su tutte le facce.
for ( int nF = 0 ; nF < GetFacetCount() ; ++ nF) {
// Dati della faccia
POLYLINEVECTOR vLoopVec ;
GetFacetLoops( nF, vLoopVec) ;
if ( vLoopVec.empty())
continue ;
// Verifico la posizione del loop esterno
int nIntType = VerifyLoopPlane( vLoopVec[0], plPlane) ;
// Se interseca il piano di taglio, calcolo la divisione della faccia
LineFacetClassVector IntersLinePart ;
if ( nIntType == FPI_CUT) {
PtrOwner<SurfFlatRegion> pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ;
if ( IsNull( pReg) || ! pReg->IsValid())
return false ;
nIntType = IntersFacetPlane( *pReg, plPlane, IntersLinePart) ;
}
// Gestione dei risultati
if ( nIntType == FPI_CUT) {
for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) {
// Salvo intersezione per la faccia.
auto it = IntersLineMap.find( nF) ;
if ( it != IntersLineMap.end()) {
it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ;
}
else {
IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ;
}
}
}
else if ( nIntType == FPI_ON) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
Vector3d vtNf ;
GetFacetNormal( nF, vtNf) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = ( vtNf * plPlane.GetVersN() > 0 ? 2 : -2) ;
}
else if ( nIntType == FPI_IN) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = 1 ;
}
else if ( nIntType == FPI_OUT) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = -1 ;
}
else
return false ;
}
// Divido le facce.
PieceMap NewFacet ;
SplitFacet( IntersLineMap, NewFacet) ;
INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ;
RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ;
// Elimino i triangoli superflui
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
if ( m_vTria[nT].nTempPart == 0 ||
m_vTria[nT].nTempPart == -1 ||
m_vTria[nT].nTempPart == -2 ||
( ! bSaveOnEq && m_vTria[nT].nTempPart == 2)) {
RemoveTriangle( nT) ;
bModif = true ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Risultato : 0=nessuna intersezione, 1=intersezione è un punto, 2=intersezione è un segmento
static int
+5 -3
View File
@@ -482,12 +482,14 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
// verifico appartenga alla stessa faccia
if ( m_vTria[nAdjT].nIdFacet != nF)
return false ;
// recupero il suo lato di adiacenza
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
int nAdjS = SVT_NULL ;
for ( int i = 0 ; i < 3 ; ++ i) {
if ( m_vTria[nAdjT].nIdAdjac[i] == nT) {
nAdjS = i ;
break ;
if ( nAdjS == SVT_NULL)
nAdjS = i ;
else
return false ;
}
}
if ( nAdjS == SVT_NULL)
+100 -4
View File
@@ -12,17 +12,112 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Triangulate.h"
#include "SurfTriMesh.h"
#include "CurveLine.h"
#include "Triangulate.h"
#include "DistPointLine.h"
#include "DistLineLine.h"
#include <unordered_map>
using namespace std ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemoveTJunctions(void)
SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
{
bModified = false ;
// ciclo sui triangoli
int nTriaNum = GetTriangleSize() ;
for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {
// se cancellato passo al successivo
if ( m_vTria[nT].nIdVert[0] == SVT_DEL)
continue ;
// recupero i vertici dei triangoli
int nIdV[3] ;
GetTriangle( nT, nIdV) ;
// ciclo sui triangoli adiacenti
for ( int nE = 0 ; nE < 3 ; ++ nE) {
// recupero triangolo adiacente, se non esiste passo al successivo
int nAdjT = m_vTria[nT].nIdAdjac[nE] ;
if ( nAdjT == SVT_NULL || nAdjT == SVT_DEL)
continue ;
// recupero i vertici del triangolo adiacente
int nAdjIdV[3] ;
GetTriangle( nAdjT, nAdjIdV) ;
// verifico se questi vertici coincidono con quelli del triangolo di riferimento
int nCoinc = 0 ;
for ( int i = 0 ; i < 3 ; ++ i) {
for ( int j = 0 ; j < 3 ; ++ j) {
if ( nIdV[i] == nAdjIdV[j])
++ nCoinc ;
}
}
if ( nCoinc == 3) {
RemoveTriangle( nAdjT) ;
bModified = true ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::FlipTriangles( int nTA, int nTB)
{
// Verifico esistenza triangoli
if ( ! ExistsTriangle( nTA) || ! ExistsTriangle( nTB))
return false ;
// Verifico adiacenza triangoli
int nEdgeA ;
for ( nEdgeA = 0 ; nEdgeA < 3 ; ++ nEdgeA) {
if ( m_vTria[nTA].nIdAdjac[nEdgeA] == nTB)
break ;
}
int nEdgeB ;
for ( nEdgeB = 0 ; nEdgeB < 3 ; ++ nEdgeB) {
if ( m_vTria[nTB].nIdAdjac[nEdgeB] == nTA)
break ;
}
// Se non sono adiacenti tra loro, impossibile flip
if ( nEdgeA == 3 && nEdgeB == 3)
return false ;
// Recupero i vertici del triangolo A
Point3d ptSegSt, ptSegEn, ptVertA ;
if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) ||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
return false ;
// Recupero il vertice opposto del triangolo B
Point3d ptVertB ;
if ( ! GetVertex( m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3], ptVertB))
return false ;
// Verifico se possibile il flip (le diagonali del quadrilatero si intersecano internamente)
DistLineLine DiagDist( ptSegSt, ptSegEn, ptVertA, ptVertB) ;
if ( ! DiagDist.IsSmall())
return false ;
double dPos1, dPos2 ;
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2) ||
dPos1 < EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() - EPS_SMALL ||
dPos2 < EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() - EPS_SMALL)
return false ;
// Eseguo il flipping
m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ;
m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ;
m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ;
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ;
m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemoveTJunctions( bool& bModified)
{
bModified = false ;
// Vettore di indici dei vertici sui lati del triangolo corrente
unordered_map< int, INTVECTOR> TriaMap ;
@@ -72,13 +167,13 @@ SurfTriMesh::RemoveTJunctions(void)
}
}
// Riordino i vertici sul segmento
auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2)
auto SortVertices = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2)
{ Point3d ptV1, ptV2 ;
GetVertex( nV1, ptV1) ;
GetVertex( nV2, ptV2) ;
return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ;
} ;
sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ;
sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVertices) ;
}
// Se ci sono più di 3 vertici
if ( vVertOtl.size() > 3) {
@@ -107,6 +202,7 @@ SurfTriMesh::RemoveTJunctions(void)
// Rimuovo il triangolo
int nTFlag = m_vTria[nT].nTFlag ;
RemoveTriangle( nT) ;
bModified = true ;
// Aggiungo i nuovi triangoli
int nLastNewTria = SVT_NULL ;
// Se ci sono 4 vertici, inserisco due triangoli