diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 83fcc4e..775aa5b 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/Polygon3d.cpp b/Polygon3d.cpp index a324c01..e7c2c48 100644 --- a/Polygon3d.cpp +++ b/Polygon3d.cpp @@ -104,7 +104,8 @@ Polygon3d::FromPolyLine( const PolyLine& PL) //---------------------------------------------------------------------------- bool -Polygon3d::FromPlaneTrimmedWithBox( const Plane3d& plPlane, const Point3d& ptMin, const Point3d& ptMax, bool bOnEq, bool bOnCt) +Polygon3d::FromPlaneTrimmedWithBox( const Plane3d& plPlane, + const Point3d& ptMin, const Point3d& ptMax, bool bOnEq, bool bOnCt, double dToler) { // pulisco tutto Clear() ; @@ -112,17 +113,32 @@ Polygon3d::FromPlaneTrimmedWithBox( const Plane3d& plPlane, const Point3d& ptMin if ( plPlane.GetVersN().IsSmall() || AreSamePointApprox( ptMin, ptMax)) return false ; // assegno il piano - m_Plane = plPlane ; + Plane3d plTemp = plPlane ; + // se piano molto vicino ad uno dei vertici del box, lo faccio passare esattamente per il vertice + if ( dToler > EPS_SMALL) { + PNTVECTOR vBoxVert = { Point3d( ptMin.x, ptMin.y, ptMin.z), Point3d( ptMin.x, ptMin.y, ptMax.z), + Point3d( ptMax.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMin.y, ptMax.z), + Point3d( ptMin.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMax.y, ptMax.z), + Point3d( ptMax.x, ptMax.y, ptMin.z), Point3d( ptMax.x, ptMax.y, ptMax.z)} ; + for ( const auto& ptP : vBoxVert) { + if ( abs( DistPointPlane( ptP, plTemp)) < dToler) { + Point3d ptNear = ProjectPointOnPlane( ptP, plTemp) ; + Vector3d vtDelta = ptP - ptNear ; + plTemp.Offset( vtDelta * plTemp.GetVersN()) ; + break ; + } + } + } // centro del box proiettato nel piano Point3d ptCen = Media( ptMin, ptMax, 0.5) ; - ptCen -= (( ptCen - ORIG) * plPlane.GetVersN() - plPlane.GetDist()) * plPlane.GetVersN() ; + ptCen -= (( ptCen - ORIG) * plTemp.GetVersN() - plTemp.GetDist()) * plTemp.GetVersN() ; // raggio del box double dDiam = Dist( ptMin, ptMax) ; // poligono nel suo piano FromRectangle( dDiam, dDiam) ; // riferimento del piano Frame3d frRef ; - frRef.Set( ptCen, plPlane.GetVersN(), FromUprightOrtho( plPlane.GetVersN())) ; + frRef.Set( ptCen, plTemp.GetVersN(), FromUprightOrtho( plTemp.GetVersN())) ; ToGlob( frRef) ; // lo trimmo con le facce del box Plane3d plFace ; @@ -138,14 +154,22 @@ Polygon3d::FromPlaneTrimmedWithBox( const Plane3d& plPlane, const Point3d& ptMin Trim( plFace, true, bOnEq, bOnCt) ; plFace.Set( ptMax.x, X_AX) ; // faccia 6 (Norm = X+) Trim( plFace, true, bOnEq, bOnCt) ; - + // elimino eventuali vertici coincidenti + for ( int i = 1 ; i < int( m_vVert.size()) ;) { + if ( SqDist( m_vVert[i], m_vVert[i-1]) < SQ_EPS_SMALL) { + m_vVert[i-1] = Media( m_vVert[i-1], m_vVert[i]) ; + m_vVert.erase( m_vVert.begin() + i) ; + } + else + ++ i ; + } return true ; } //---------------------------------------------------------------------------- bool Polygon3d::FromPlaneTrimmedWithBox( const Point3d& ptOn, const Vector3d& vtN, - const Point3d& ptMin, const Point3d& ptMax, bool bOnEq, bool bOnCt) + const Point3d& ptMin, const Point3d& ptMax, bool bOnEq, bool bOnCt, double dToler) { Plane3d plPlane ; plPlane.Set( ptOn, vtN) ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index f91c87f..93a8db8 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- // EgalTech 2019-2020 //---------------------------------------------------------------------------- -// File : SurfTriMeshBooleans.cpp Data : 04.04.20 Versione : 2.2d1 +// File : SurfTriMeshBooleans.cpp Data : 01.10.20 Versione : 2.2j1 // Contenuto : Implementazione delle funzioni booleane per SurfFTrimesh. // // // // Modifiche : 10.05.19 LM Creazione modulo. -// +// 01.10.20 LM Aggiunte scalature 1024x. // //---------------------------------------------------------------------------- @@ -955,7 +955,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT // Creo i loop ChainCurves LoopCreator ; - LoopCreator.Init( false, EPS_SMALL, int( it->second.size())) ; + LoopCreator.Init( false, 10 * EPS_SMALL, int( it->second.size())) ; // Carico le curve per concatenarle for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) { Point3d ptSt = it->second[nCv].ptSt ; @@ -1390,7 +1390,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } // Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso - PNTULIST ExternLoopList = vPolygons[0].GetUPointList() ; + PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ; // Ciclo sui segmenti del loop esterno auto itSt = ExternLoopList.begin() ; auto itEn = itSt ; @@ -1408,6 +1408,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT for ( int nInnPoly = 1 ; nInnPoly < int( vPolygons.size()) ; ++ nInnPoly) { // Ciclo sui punti dei loop interni Point3d ptInnPoint ; + bool bIsFirst = true ; bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ; while ( bContinue) { DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ; @@ -1418,8 +1419,10 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT POINTU NewPointU ; NewPointU.first = ptInnPoint ; NewPointU.second = dLongPos ; - vPointWithOrder.emplace_back( NewPointU) ; + if ( ! bIsFirst) + vPointWithOrder.emplace_back( NewPointU) ; } + bIsFirst = false ; bContinue = vPolygons[nInnPoly].GetNextPoint( ptInnPoint) ; } } @@ -1459,7 +1462,120 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } } } + // Divido i loop che si autointercettano + int nInitialLoopNum = int( vPolygons.size()) ; + for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) { + // Lista dei punti della PolyLine Loop corrente + PNTULIST& LoopPointList = vPolygons[nL].GetUPointList() ; + // Ciclo sui segmenti + auto itSt = LoopPointList.begin() ; + auto itEn = itSt ; + ++ itEn ; + for ( ; itSt != LoopPointList.end() && itEn != LoopPointList.end() ; ++ itSt, ++ itEn) { + // Segmento corrente + Point3d ptSt = itSt->first ; + Point3d ptEn = itEn->first ; + Vector3d vtSeg = ptEn - ptSt ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + // Lista di punti da aggiungere al segmento corrente + PNTUVECTOR vAddingPointWithOrder ; + // Ciclo su tutti i punti non del segmento corrente + auto itP = LoopPointList.begin() ; + for ( ; itP != LoopPointList.end() ; ++ itP) { + if ( itP != itSt && itP != itEn) { + Point3d ptP = itP->first ; + DistPointLine DistCalculator( ptP, ptSt, ptEn) ; + double dDist ; + DistCalculator.GetDist( dDist) ; + double dLongPos = ( ptP - ptSt) * vtSeg ; + if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) { + POINTU NewPointU ; + NewPointU.first = ptP ; + NewPointU.second = dLongPos ; + vAddingPointWithOrder.emplace_back( NewPointU) ; + } + } + } + // Riordino i punti interni sul segmento esterno in funzione della distanza dall'origine di esso + for ( int nPi = 0 ; nPi < int( vAddingPointWithOrder.size()) - 1 ; ++ nPi) { + for ( int nPj = nPi + 1 ; nPj < int( vAddingPointWithOrder.size()) ; ++ nPj) { + if ( vAddingPointWithOrder[nPi].second > vAddingPointWithOrder[nPj].second) { + swap( vAddingPointWithOrder[nPi], vAddingPointWithOrder[nPj]) ; + } + } + } + // Aggiungo i punti al loop esterno + for ( int nPi = 0 ; nPi < int( vAddingPointWithOrder.size()) ; ++ nPi) { + itSt = LoopPointList.emplace( itEn, vAddingPointWithOrder[nPi]) ; + } + } + // Spezzo i loop autointersecantesi + + POLYLINEVECTOR vAuxPolygons ; + vAuxPolygons.emplace_back( vPolygons[nL]) ; + bool bSplitted = true ; + while ( bSplitted) { + bSplitted = false ; + for ( int nl = 0 ; nl < int( vAuxPolygons.size()) ; ++ nl) { + PNTULIST& PntLst = vAuxPolygons[nl].GetUPointList() ; + std::vector vPoint ; + for ( auto it = PntLst.begin() ; it != PntLst.end() ; ++ it) { + vPoint.emplace_back( it->first) ; + } + int nStartPt = -1 ; + int nEndPt = int( vPoint.size()) ; + for ( int ni = 0 ; ni < int( vPoint.size()) - 1 ; ++ ni) { + for ( int nj = ni + 1 ; nj < int( vPoint.size()) ; ++ nj) { + if ( ( ni != 0 || nj != int( vPoint.size()) - 1) && + AreSamePointApprox( vPoint[ni], vPoint[nj])) { + nStartPt = ni ; + nEndPt = nj ; + break ; + } + } + } + if ( nStartPt != -1 && nEndPt != int( vPoint.size())) { + PolyLine CurAuxLoop1, CurAuxLoop2 ; + for ( int ni = 0 ; ni < int( vPoint.size()) ; ++ ni) { + if ( ni < nStartPt || ni >= nEndPt) + CurAuxLoop1.AddUPoint( 0., vPoint[ni]) ; + else + CurAuxLoop2.AddUPoint( 0., vPoint[ni]) ; + } + CurAuxLoop2.AddUPoint( 0., vPoint[nStartPt]) ; + vAuxPolygons[nl].Clear() ; + Point3d ptP ; + bool bContinue = CurAuxLoop1.GetFirstPoint( ptP) ; + while ( bContinue) { + vAuxPolygons[nl].AddUPoint( 0., ptP) ; + bContinue = CurAuxLoop1.GetNextPoint( ptP) ; + } + vAuxPolygons.emplace_back( CurAuxLoop2) ; + bSplitted = true ; + } + } + } + bool bReplaced = false ; + for ( int nl = 0 ; nl < int( vAuxPolygons.size()) ; ++ nl) { + if ( true/*vAuxPolygons.GetAreaXY(double& dArea)*/) { + if ( ! bReplaced) { + vPolygons[nL].Clear() ; + Point3d ptP ; + bool bContinue = vAuxPolygons[nl].GetFirstPoint( ptP) ; + while ( bContinue) { + vPolygons[nL].AddUPoint( 0., ptP) ; + bContinue = vAuxPolygons[nl].GetNextPoint( ptP) ; + } + bReplaced = true ; + } + else { + vPolygons.emplace_back( vAuxPolygons[nl]) ; + } + } + } + } for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { vPolygons[nL].Invert() ; if ( Triangulate().Make( vPolygons[nL], vPt, vTr)) { @@ -2270,6 +2386,10 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) m_OGrMgr.Clear() ; SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + Frame3d frScalingRef ; + frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + Scale( frScalingRef, 1024., 1024., 1024.) ; + SurfB.Scale( frScalingRef, 1024., 1024., 1024.) ; IntersectTriMeshTriangle( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; @@ -2297,7 +2417,9 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) if ( ! AdjustVertices() || ! DoCompacting()) return false ; RemoveTJunctions() ; - return ( AdjustVertices() && DoCompacting()) ; + bool bResult = ( AdjustVertices() && DoCompacting()) ; + Scale( frScalingRef, 1. / 1024., 1. / 1024., 1. / 1024.) ; + return bResult ; } //---------------------------------------------------------------------------- @@ -2307,6 +2429,10 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) m_OGrMgr.Clear() ; SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + Frame3d frScalingRef ; + frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + Scale( frScalingRef, 1024., 1024., 1024.) ; + SurfB.Scale( frScalingRef, 1024., 1024., 1024.) ; IntersectTriMeshTriangle( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; @@ -2334,7 +2460,9 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) if ( ! AdjustVertices() || ! DoCompacting()) return false ; RemoveTJunctions() ; - return ( AdjustVertices() && DoCompacting()) ; + bool bResult = ( AdjustVertices() && DoCompacting()) ; + Scale( frScalingRef, 1. / 1024., 1. / 1024., 1. / 1024.) ; + return bResult ; } //---------------------------------------------------------------------------- @@ -2344,6 +2472,10 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) m_OGrMgr.Clear() ; SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + Frame3d frScalingRef; + frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + Scale( frScalingRef, 1024., 1024., 1024.) ; + SurfB.Scale( frScalingRef, 1024., 1024., 1024.) ; IntersectTriMeshTriangle( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; @@ -2372,7 +2504,9 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) if ( ! AdjustVertices() || ! DoCompacting()) return false ; RemoveTJunctions() ; - return ( AdjustVertices() && DoCompacting()) ; + bool bResult = ( AdjustVertices() && DoCompacting()) ; + Scale( frScalingRef, 1. / 1024., 1. / 1024., 1. / 1024.) ; + return bResult ; } //---------------------------------------------------------------------------- @@ -2385,8 +2519,13 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf, return false ; SurfTriMesh SurfC ; SurfC.CopyFrom( &ClassifierSurf) ; + Frame3d frScalingRef ; + frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + Scale( frScalingRef, 1024., 1024., 1024.) ; + SurfC.Scale( frScalingRef, 1024., 1024., 1024.) ; IntersectTriMeshTriangle( SurfC) ; IdentifyParts() ; + Scale( frScalingRef, 1. / 1024., 1. / 1024., 1. / 1024.) ; int nTriaNum = GetTriangleSize() ; for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {