From 068681c47478e5192b8753d945d64b0efbfc59db Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Tue, 12 Nov 2019 07:44:51 +0000 Subject: [PATCH] EgtGeomKernel : - migliorie nella intersezione tra triangoli - correzione a IntersSurfTmSurfTm che non interpretava correttamente i nuovi risultati di IntersTriaTria - correzioni a Zmap per Mortising con movimento nel piano ma non perpendicolare all'asse dell'utensile. --- IntersSurfTmSurfTm.cpp | 3 +- IntersTriaTria.cpp | 52 ++++++++++++++++++++++--------- SurfTriMeshBooleans.cpp | 23 +++++++------- VolZmapVolume.cpp | 69 ++++++++++++++++++++++++----------------- 4 files changed, 91 insertions(+), 56 deletions(-) diff --git a/IntersSurfTmSurfTm.cpp b/IntersSurfTmSurfTm.cpp index 2fb0ebf..48a2792 100644 --- a/IntersSurfTmSurfTm.cpp +++ b/IntersSurfTmSurfTm.cpp @@ -75,7 +75,8 @@ IntersSurfTmSurfTm( const ISurfTriMesh& Stm1, const ISurfTriMesh& Stm2, // intersezione tra i triangoli Point3d ptInt, ptInt2 ; TRIA3DVECTOR vIttTria ; - int nRes = IntersTriaTria( TriaA, TriaB, ptInt, ptInt2, vIttTria) ; + int nResEx = IntersTriaTria( TriaA, TriaB, ptInt, ptInt2, vIttTria) ; + int nRes = FromSpecialToNormal( nResEx) ; // se punto if ( nRes == ITTT_VERT || nRes == ITTT_PNT) { // verifico se punto già inserito diff --git a/IntersTriaTria.cpp b/IntersTriaTria.cpp index 8cc3e92..1763205 100644 --- a/IntersTriaTria.cpp +++ b/IntersTriaTria.cpp @@ -78,23 +78,30 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p if ( nVertPos2 == 3 || nVertNeg2 == 3) return ITTT_NO ; - // se i triangoli sono complanari - if ( ( nVertPos1 == 0 && nVertNeg1 == 0) || ( nVertPos2 == 0 && nVertNeg2 == 0)) - return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ; - // intersezione tra i piani dei due triangoli Point3d ptL1 ; Vector3d vtL1 ; - if ( IntersPlanePlane( plTria1, plTria2, ptL1, vtL1) != IPPT_YES) + int nresPP = IntersPlanePlane( plTria1, plTria2, ptL1, vtL1) ; + if ( nresPP == IPPT_NO) return ITTT_NO ; + // se i triangoli sono complanari + if ( nresPP == IPPT_OVERLAPS) + return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ; + // limito la linea di intersezione con il primo triangolo int nRes1 = IntersCoplanarLineTria( ptL1, vtL1, 100.0, trTria1, ptInt, ptInt2, false) ; + if ( nRes1 == ILTT_NO) + return ITTT_NO ; // il segmento calcolato va limitato col secondo triangolo Point3d ptL2 = ptInt ; - Vector3d vtL2 = ptInt2 - ptInt ; - double dLen = vtL2.Len() ; - vtL2 /= dLen ; + Vector3d vtL2 = vtL1 ; + double dLen = 0 ; + if ( nRes1 != ILTT_VERT) { + vtL2 = ptInt2 - ptInt ; + dLen = vtL2.Len() ; + vtL2 /= dLen ; + } int nRes2 = IntersCoplanarLineTria( ptL2, vtL2, dLen, trTria2, ptInt, ptInt2, true) ; return nTriaTriaIntersCases[nRes1][nRes2] ; @@ -104,14 +111,18 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p int IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TRIA3DVECTOR& vTria) { + // determino il piano medio dei due triangoli + Plane3d plMed ; + plMed.Set( ( trTria2.GetCentroid() + trTria2.GetCentroid()) / 2, trTria1.GetN() + trTria2.GetN()) ; + // creo la regione equivalente al primo triangolo SurfFlatRegion sfrTria1 ; PtrOwner pCcTria1( CreateBasicCurveComposite()) ; if ( IsNull( pCcTria1)) return ITTT_NO ; - pCcTria1->AddPoint( trTria1.GetP( 0)) ; - pCcTria1->AddLine( trTria1.GetP( 1)) ; - pCcTria1->AddLine( trTria1.GetP( 2)) ; + pCcTria1->AddPoint( ProjectPointOnPlane( trTria1.GetP( 0), plMed)) ; + pCcTria1->AddLine( ProjectPointOnPlane( trTria1.GetP( 1), plMed)) ; + pCcTria1->AddLine( ProjectPointOnPlane( trTria1.GetP( 2), plMed)) ; pCcTria1->Close() ; if ( ! sfrTria1.AddExtLoop( Release( pCcTria1))) return ITTT_NO ; @@ -121,9 +132,9 @@ IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TR PtrOwner pCcTria2( CreateBasicCurveComposite()) ; if ( IsNull( pCcTria2)) return ITTT_NO ; - pCcTria2->AddPoint( trTria2.GetP( 0)) ; - pCcTria2->AddLine( trTria2.GetP( 1)) ; - pCcTria2->AddLine( trTria2.GetP( 2)) ; + pCcTria2->AddPoint( ProjectPointOnPlane( trTria2.GetP( 0), plMed)) ; + pCcTria2->AddLine( ProjectPointOnPlane( trTria2.GetP( 1), plMed)) ; + pCcTria2->AddLine( ProjectPointOnPlane( trTria2.GetP( 2), plMed)) ; pCcTria2->Close() ; if ( ! sfrTria2.AddExtLoop( Release( pCcTria2))) return ITTT_NO ; @@ -136,8 +147,19 @@ IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TR // recupero il contorno esterno del risultato come polilinea PolyLine PL ; - if ( ! sfrTria1.ApproxLoopWithLines( 0, 0, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) + PtrOwner pLoop( sfrTria1.GetLoop( 0, 0)) ; + if ( IsNull( pLoop) || pLoop->GetType() != CRV_COMPO) return ITTT_NO ; + ICurveComposite* pCoLoop = GetBasicCurveComposite( pLoop) ; + for ( int i = 0 ; i < pCoLoop->GetCurveCount() ; ++ i) { + const ICurve* pCrv = pCoLoop->GetCurve( i) ; + if ( i == 0) { + Point3d ptS ; pCrv->GetStartPoint( ptS) ; + PL.AddUPoint( i, ptS) ; + } + Point3d ptE ; pCrv->GetEndPoint( ptE) ; + PL.AddUPoint( i+1, ptE) ; + } // eseguo una triangolazione del contorno chiuso PNTVECTOR vPnt ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 6815aab..b3224e1 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -51,9 +51,9 @@ IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3 Point3d ptIntA1, ptIntA2 ; TRIA3DVECTOR vTriaA ; int nIntTypeA = IntersTriaTria( trTria, trTriaA, ptIntA1, ptIntA2, vTriaA) ; - if ( nFromSpecialToNormal[nIntTypeA] == ITTT_PNT || nFromSpecialToNormal[nIntTypeA] == ITTT_VERT) + if ( FromSpecialToNormal( nIntTypeA) == ITTT_PNT || FromSpecialToNormal( nIntTypeA) == ITTT_VERT) nIntA = 1 ; - else if ( nFromSpecialToNormal[nIntTypeA] == ITTT_YES || nFromSpecialToNormal[nIntTypeA] == ITTT_EDGE) { + else if ( FromSpecialToNormal( nIntTypeA) == ITTT_YES || FromSpecialToNormal( nIntTypeA) == ITTT_EDGE) { nIntA = 2 ; } // Interseco il triangolo con il secondo dei due triangoli del rettangolo @@ -61,9 +61,9 @@ IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3 Point3d ptIntB1, ptIntB2 ; TRIA3DVECTOR vTriaB ; int nIntTypeB = IntersTriaTria( trTria, trTriaB, ptIntB1, ptIntB2, vTriaB) ; - if ( nFromSpecialToNormal[nIntTypeB] == ITTT_PNT || nFromSpecialToNormal[nIntTypeB] == ITTT_VERT) + if ( FromSpecialToNormal( nIntTypeB) == ITTT_PNT || FromSpecialToNormal( nIntTypeB) == ITTT_VERT) nIntB = 1 ; - else if ( nFromSpecialToNormal[nIntTypeB] == ITTT_YES || nFromSpecialToNormal[nIntTypeB] == ITTT_EDGE) { + else if ( FromSpecialToNormal( nIntTypeB) == ITTT_YES || FromSpecialToNormal( nIntTypeB) == ITTT_EDGE) { nIntB = 2 ; } // Unisco le due intersezioni @@ -911,8 +911,8 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) if ( m_nStatus != OK || ! SurfB.IsValid()) return false ; // Unordered map dei segmenti di intersezione - std::unordered_map LineMapA ; - std::unordered_map LineMapB ; + unordered_map LineMapA ; + unordered_map LineMapB ; // Ciclo sui triangoli delle mesh int nTriaNumA = GetTriangleSize() ; int nTriaNumB = SurfB.GetTriangleSize() ; @@ -946,12 +946,12 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) Point3d ptSegSt, ptSegEn ; TRIA3DVECTOR vTria ; int nIntType = IntersTriaTria( trTriaA, trTriaB, ptSegSt, ptSegEn, vTria) ; - if ( ! ( nFromSpecialToNormal[nIntType] == ITTT_NO || - nFromSpecialToNormal[nIntType] == ITTT_OVERLAPS || - nFromSpecialToNormal[nIntType] == ITTTS_VERT_VERT)) { + if ( ! ( FromSpecialToNormal( nIntType) == ITTT_NO || + FromSpecialToNormal( nIntType) == ITTT_OVERLAPS || + FromSpecialToNormal( nIntType) == ITTTS_VERT_VERT)) { // Assegno i dati di intersezione IntSegment CurInters ; - if ( nFromSpecialToNormal[nIntType] == ITTT_EDGE || nFromSpecialToNormal[nIntType] == ITTT_YES) { + if ( FromSpecialToNormal( nIntType) == ITTT_EDGE || FromSpecialToNormal( nIntType) == ITTT_YES) { CurInters.ptSt = ptSegSt ; CurInters.ptEn = ptSegEn ; CurInters.bDegenerate = false ; @@ -1035,7 +1035,6 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) } } } - // Ritriangolarizzo i triangoli della superficie A for ( auto it = LineMapA.begin() ; it != LineMapA.end() ; ++ it) { @@ -1762,6 +1761,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) vInnerLoop.resize( 0) ; } } + // Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra. if ( ! bModif) { int nVertNum = 0 ; @@ -1848,6 +1848,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) // Se avvenuta modifica, aggiorno tutto if ( bModif) bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ; + // Triangoli sovrapposti if ( bContinue) { int nTriaNumA = GetTriangleSize() ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index 9d0cdb7..6830b70 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -611,7 +611,7 @@ VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& Mrt_ZMilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : - Chs_ZMilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; + Chs_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } @@ -628,6 +628,10 @@ VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& break ; case Tool::CONEMILL : Conus_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; + break ; + case Tool::MORTISER : + Mrt_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; + break ; } } } @@ -697,6 +701,9 @@ VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& case Tool::CONEMILL : Conus_XYMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; + case Tool::MORTISER : + Mrt_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; + break ; } } } @@ -745,9 +752,7 @@ VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& Conus_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : - // ammesso solo movimento perpendicolare all'asse utensile - if ( dSqLLong < EPS_SMALL * EPS_SMALL) - Mrt_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; + Mrt_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : // ammesso solo movimento perpendicolare all'asse utensile @@ -1601,12 +1606,10 @@ VolZmap::Mrt_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const { // Proiezione della traiettoria sul piano di movimento Vector3d vtPlV = vtToolDir ^ vtAux ; - if ( vtPlV * ( ptE - ptS) < 0) vtPlV *= - 1 ; - Point3d ptPlS = ptS ; - Point3d ptPlE = ptS + ( ptE - ptS) * vtPlV * vtPlV ; + Point3d ptPlE = ptS + ( ( ptE - ptS) - ( ptE - ptS) * vtAux * vtAux) ; // Scompongo la mortasatrice in solidi semplici @@ -1615,7 +1618,7 @@ VolZmap::Mrt_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const double dLenY = m_Tool.GetMrtChsThickness() ; double dLenZ = m_Tool.GetHeigth() - m_Tool.GetCornRadius() ; - CompPar_ZMilling( nGrid, dLenX, dLenY, dLenZ, ptPlS, ptPlE, vtToolDir, vtAux) ; + CompPar_Milling( nGrid, dLenX, dLenY, dLenZ, ptPlS, ptPlE, vtToolDir, vtAux) ; // Se la punta è di tipo bull-nose if ( abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) > EPS_SMALL) { @@ -1626,12 +1629,15 @@ VolZmap::Mrt_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const dLenX = abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) ; dLenZ = m_Tool.GetCornRadius() ; - // Cilindro ( il moto dei due cilindri si sovrappone, quindi è inutile + CompPar_Milling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux) ; + // Cilindri ( il moto dei due cilindri non sempre si sovrappone, quindi è fondamentale // eseguire due volte il conto - Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; - Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; - - CompCyl_Milling( nGrid, ptSminus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; + Point3d ptSCyl = ptTipS - ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; + Point3d ptECyl = ptTipE - ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; + CompCyl_Milling( nGrid, ptSCyl, ptECyl, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; + ptSCyl = ptTipS + ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; + ptECyl = ptTipE + ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; + CompCyl_Milling( nGrid, ptSCyl, ptECyl, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } // se la punta è di tipo sfera @@ -2792,9 +2798,11 @@ bool VolZmap::Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano dei movimenti possibili - Point3d ptSp = ptS ; - Vector3d vtMoveDir = vtToolDir ^ vtAux ; - Point3d ptEp = ptS + ( ptE - ptS) * vtMoveDir * vtMoveDir ; + Vector3d vtVOnP = vtToolDir ^ vtAux ; + if ( vtVOnP * ( ptE - ptS) < 0) + vtVOnP *= -1 ; + Point3d ptPlS = ptS ; + Point3d ptPlE = ptS + ( ( ptE - ptS) - (ptE - ptS) * vtAux * vtAux) ; // Scompongo la mortasatrice in solidi semplici @@ -2803,35 +2811,38 @@ VolZmap::Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const V double dLenY = m_Tool.GetMrtChsThickness() ; double dLenZ = m_Tool.GetHeigth() - m_Tool.GetCornRadius() ; - CompPar_Milling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEp, vtToolDir, vtAux) ; + Point3d ptBasePS = ptPlS - 0.5 * dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; + Point3d ptBasePE = ptPlE - 0.5 * dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; + CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptBasePS, ptBasePE, vtAux, vtToolDir) ; // Se la punta è di tipo bull-nose if ( abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta - Point3d ptTipS = ptS - dLenZ * vtToolDir ; - Point3d ptTipE = ptEp - dLenZ * vtToolDir ; + Point3d ptTipPS = ptBasePS - 0.5 * dLenZ * vtToolDir ; + Point3d ptTipPE = ptBasePE - 0.5 * dLenZ * vtToolDir ; dLenX = abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) ; dLenZ = m_Tool.GetCornRadius() ; - Vector3d vtVOnP = vtToolDir ^ vtAux ; - if ( vtVOnP * ( ptTipE - ptTipS) < 0) - vtVOnP *= - 1 ; + ptTipPS -= 0.5 * dLenZ * vtToolDir ; + ptTipPE -= 0.5 * dLenZ * vtToolDir ; + CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptTipPS, ptTipPE, vtAux, vtToolDir) ; // Cilindri - Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; - Point3d ptEminus = ptTipE - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; - Point3d ptSplus = ptTipS + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; - Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; - CompCyl_Milling( nGrid, ptSminus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; + Point3d ptSminus = ptTipPS + 0.5 * dLenZ * vtToolDir - ( 0.5 * dLenX) * vtVOnP ; + Point3d ptEminus = ptTipPE + 0.5 * dLenZ * vtToolDir - ( 0.5 * dLenX) * vtVOnP ; + CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; + Point3d ptSplus = ptTipPS + 0.5 * dLenZ * vtToolDir + ( 0.5 * dLenX) * vtVOnP ; + Point3d ptEplus = ptTipPE + 0.5 * dLenZ * vtToolDir + ( 0.5 * dLenX) * vtVOnP ; + CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } // se la punta è di tipo sfera else { // Cilindro - Point3d ptCylS = ptS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; - Point3d ptCylE = ptEp - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; + Point3d ptCylS = ptBasePS - 0.5 * dLenZ * vtToolDir ; + Point3d ptCylE = ptBasePE - 0.5 * dLenZ * vtToolDir ; CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; }