From 9e400bee156d5e57eeb6770a1f7dc8130ef6b2d9 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Tue, 22 Aug 2017 08:06:50 +0000 Subject: [PATCH] EgtGeomKernel : - a PolyLine e PolyArc aggiunta funzione ModifyLastParam - a SurfTriMesh aggiunte funzioni GetFacetAdjacencies e GetFacetsContact. --- PolyArc.cpp | 12 ++++ PolyLine.cpp | 12 ++++ SurfTriMesh.h | 2 + SurfTriMeshFaceting.cpp | 156 +++++++++++++++++++++++++++++----------- 4 files changed, 142 insertions(+), 40 deletions(-) diff --git a/PolyArc.cpp b/PolyArc.cpp index 30a0e5b..09830c0 100644 --- a/PolyArc.cpp +++ b/PolyArc.cpp @@ -90,6 +90,18 @@ PolyArc::Close( void) return AddUPoint( m_lUPointBs.front().dU, m_lUPointBs.front().ptP, m_lUPointBs.front().dB) ; } +//---------------------------------------------------------------------------- +bool +PolyArc::ModifyLastParam( double dPar) +{ + // verifico esistano dei punti + if ( m_lUPointBs.empty()) + return false ; + // eseguo la modifica + m_lUPointBs.back().dU = dPar ; + return true ; +} + //---------------------------------------------------------------------------- bool PolyArc::ModifyLastBulge( double dBulge) diff --git a/PolyLine.cpp b/PolyLine.cpp index 4498ec9..959c943 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -81,6 +81,18 @@ PolyLine::Close( void) return AddUPoint( m_lUPoints.front().second, m_lUPoints.front().first) ; } +//---------------------------------------------------------------------------- +bool +PolyLine::ModifyLastParam( double dPar) +{ + // verifico esistano dei punti + if ( m_lUPoints.empty()) + return false ; + // eseguo la modifica + m_lUPoints.back().second = dPar ; + return true ; +} + //---------------------------------------------------------------------------- bool PolyLine::EraseFirstUPoint( void) diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 2588ac8..b30a6ec 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -172,11 +172,13 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW int GetFacetFromTria( int nT) const override ; bool GetAllTriaInFacet( int nF, INTVECTOR& vT) const override ; bool GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const override ; + bool GetFacetAdjacencies( int nF, INTMATRIX& vAdj) const override ; bool GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const override ; bool GetFacetNearestMidPoint( int nF, const Point3d& ptNear, Point3d& ptMid, Vector3d& vtN) const override ; bool GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const override ; bool GetFacetNormal( int nF, Vector3d& vtN) const override ; bool GetFacetArea( int nF, double& dArea) const override ; + bool GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Point3d& ptP2, double& dAng) const override ; SurfTriMesh* CloneFacet( int nF) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq) override ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index 94fad06..6d6716c 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -242,9 +242,6 @@ SurfTriMesh::GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& pt bFound = true ; // recupero la normale della faccia (non quella mediata del vertice) vtN = m_vTria[nT].vtN ; - //Vector3d vtN1, vtN2 ; - //if ( ! GetTriangleSmoothNormal( nT, j, vtN)) - // vtN = m_vTria[nT].vtN ; } } } @@ -306,27 +303,28 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const int nAdjT[3] ; for ( int j = 0 ; j < 3 ; ++ j) nAdjT[j] = m_vTria[nT].nIdAdjac[j] ; + // determino i facet adiacenti + int nAdjF[3] ; + for ( int j = 0 ; j < 3 ; ++ j) + nAdjF[j] = ( nAdjT[j] != SVT_NULL ? m_vTria[nAdjT[j]].nIdFacet : SVT_NULL) ; // se tutti e tre i lati sono di contorno - if ( ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF) && - ( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF) && - ( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF)) { + if ( nAdjF[0] != nF && nAdjF[1] != nF && nAdjF[2] != nF) { // ho trovato un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nAdjF[0], m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nAdjF[1], m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nAdjF[2], m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; } // se i due lati 0 e 1 sono di contorno - else if ( ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF) && - ( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF)) { + else if ( nAdjF[0] != nF && nAdjF[1] != nF) { // ho trovato l'inizio di un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nAdjF[0], m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nAdjF[1], m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo @@ -334,13 +332,12 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const return false ; } // se i due lati 1 e 2 sono di contorno - else if ( ( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF) && - ( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF)) { + else if ( nAdjF[1] != nF && nAdjF[2] != nF) { // ho trovato l'inizio di un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nAdjF[1], m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nAdjF[2], m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo @@ -348,13 +345,12 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const return false ; } // se i due lati 2 e 0 sono di contorno - else if ( ( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF) && - ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF)) { + else if ( nAdjF[2] != nF && nAdjF[0] != nF) { // ho trovato l'inizio di un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nAdjF[2], m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nAdjF[0], m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo @@ -362,11 +358,11 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const return false ; } // se il lato 0 è di contorno - else if ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF) { + else if ( nAdjF[0] != nF) { // ho trovato l'inizio di un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nAdjF[0], m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo @@ -374,11 +370,11 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const return false ; } // se il lato 1 è di contorno - else if ( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF) { + else if ( nAdjF[1] != nF) { // ho trovato l'inizio di un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nAdjF[1], m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo @@ -386,11 +382,11 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const return false ; } // se il lato 2 è di contorno - else if ( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF) { + else if ( nAdjF[2] != nF) { // ho trovato l'inizio di un loop vPL.emplace_back() ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; - vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nAdjF[2], m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( SVT_NULL, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo @@ -471,7 +467,8 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, int nAdjV = Next( nAdjS) ; // verifico se il lato successivo è un bordo int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ; - if ( nNextT == SVT_NULL || m_vTria[nNextT].nIdFacet != nF) { + int nNextF = ( nNextT != SVT_NULL ? m_vTria[nNextT].nIdFacet : SVT_NULL) ; + if ( nNextF != nF) { // se già recuperato if ( m_vTria[nAdjT].nTemp == nTimeStamp) { bEnd = true ; @@ -479,15 +476,18 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, } // dichiaro triangolo analizzato m_vTria[nAdjT].nTemp = nTimeStamp ; - // aggiungo il lato al loop + // modifico l'ultima adiacenza e aggiungo il lato al loop + PL.ModifyLastParam( nNextF) ; nAdjV = Next( nAdjV) ; - PL.AddUPoint( nAdjT, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ; + PL.AddUPoint( SVT_NULL, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ; // verifico anche il successivo nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ; - if ( nNextT == SVT_NULL || m_vTria[nNextT].nIdFacet != nF) { - // aggiungo il lato al loop + nNextF = ( nNextT != SVT_NULL ? m_vTria[nNextT].nIdFacet : SVT_NULL) ; + if ( nNextF != nF) { + // modifico l'ultima adiacenza e aggiungo il lato al loop + PL.ModifyLastParam( nNextF) ; nAdjV = Next( nAdjV) ; - PL.AddUPoint( nAdjT, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ; + PL.AddUPoint( SVT_NULL, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ; } } // devo passare al triangolo adiacente @@ -496,6 +496,82 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetFacetAdjacencies( int nF, INTMATRIX& vAdj) const +{ + // recupero i loop di contorno + POLYLINEVECTOR vPL ; + if ( ! GetFacetLoops( nF, vPL)) + return false ; + // ne ricavo le adiacenze + vAdj.resize( vPL.size()) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + vAdj[i].reserve( vPL[i].GetPointNbr()) ; + double dU ; + for ( bool bFound = vPL[i].GetFirstU( dU, true) ; bFound ; bFound = vPL[i].GetNextU( dU, true)) + vAdj[i].emplace_back( int( round( dU))) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Point3d& ptP2, double& dAng) const +{ + // recupero i loop di contorno della prima faccia + POLYLINEVECTOR vPL ; + if ( ! GetFacetLoops( nF1, vPL)) + return false ; + // verifico esistenza seconda faccia + if ( nF2 < 0 || nF2 >= int( m_vFacet.size())) + return false ; + // verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto + bAdjac = false ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + double dUs, dUe ; + Point3d ptPs, ptPe ; + for ( bool bFound = vPL[i].GetFirstULine( &dUs, &ptPs, &dUe, &ptPe) ; bFound ; bFound = vPL[i].GetNextULine( &dUs, &ptPs, &dUe, &ptPe)) { + if ( int( round( dUs)) == nF2) { + if ( ! bAdjac) { + bAdjac = true ; + ptP1 = ptPs ; + ptP2 = ptPe ; + } + else { + // parametri del segmento già definito + Vector3d vtT ; + double dLen ; + DirDist( ptP1, ptP2, vtT, dLen) ; + // punto start rispetto al segmento + double dPs = ( ptPs - ptP1) * vtT ; + if ( dPs < - EPS_SMALL) + ptP1 = ptPs ; + else if ( dPs > dLen + EPS_SMALL) + ptP2 = ptPs ; + // punto end rispetto al segmento + double dPe = ( ptPe - ptP1) * vtT ; + if ( dPe < - EPS_SMALL) + ptP1 = ptPe ; + else if ( dPe > dLen + EPS_SMALL) + ptP2 = ptPe ; + } + } + } + } + // se facce in contatto, calcolo l'angolo che formano ( 0 = allineate, > 0 convesse, < 0 concave) + if ( bAdjac) { + Vector3d vtN1 = m_vTria[m_vFacet[nF1]].vtN ; + Vector3d vtN2 = m_vTria[m_vFacet[nF2]].vtN ; + Vector3d vtCm = ptP2 - ptP1 ; + bool bDet ; + if ( ! vtN1.GetRotation( vtN2, vtCm, dAng, bDet) || ! bDet) + return false ; + } + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const