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:
+5
-5
@@ -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
@@ -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
@@ -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 ;
|
||||
} ;
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+3
-90
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user