//---------------------------------------------------------------------------- // EgalTech 2015-2017 //---------------------------------------------------------------------------- // File : BtlGeom.cpp Data : 12.03.17 Versione : 1.8c2 // Contenuto : Implementazione delle funzioni sui processi per BtlGeom. // // // // Modifiche : 27.08.15 DS Creazione modulo. // 05.12.16 DS Agg. import forature. // 12.03.17 DS Agg. import tenoni e mortase. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "BtlGeom.h" #include "Polygon3d.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- #define IS_CUT( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 10) #define IS_LONGIT_CUT( nG, nP) ( ( nGroup == 0 || nGroup == 3 || nGroup == 4) && nProc == 10) #define IS_DOUBLE_CUT( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 11) #define IS_RIDGEVALLEY_CUT( nG, nP) ( ( nGroup == 0) && nProc == 12) #define IS_LAP_JOINT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 30) #define IS_NOTCH( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 32) #define IS_SEATHING_CUT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 34) #define IS_DRILL( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 40) #define IS_TENON( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 50) #define IS_MORTISE( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 50) #define IS_MORTISE_FRONT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 51) #define IS_TEXT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 61) //---------------------------------------------------------------------------- bool BtlGeom::GetProcessParamInfos( int nGroup, int nProc, int nSide, INTVECTOR& vnDPar, int& nSPar, DBLVECTOR& vdPar, string& sPar) const { // se taglio if ( IS_CUT( nGroup, nProc)) { vnDPar.reserve( 5) ; vdPar.reserve( 5) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 3) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; nSPar = 0 ; sPar.empty() ; return true ; } // se taglio longitudinale if ( IS_LONGIT_CUT( nGroup, nProc)) { vnDPar.reserve( 8) ; vdPar.reserve( 8) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 90) ; nSPar = 0 ; sPar.empty() ; return true ; } // se taglio doppio if ( IS_DOUBLE_CUT( nGroup, nProc)) { vnDPar.reserve( 6) ; vdPar.reserve( 6) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 50) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 90) ; nSPar = 0 ; sPar.empty() ; return true ; } // se taglio doppio longitudinale if ( IS_RIDGEVALLEY_CUT( nGroup, nProc)) { vnDPar.reserve( 11) ; vdPar.reserve( 11) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0.5 * GetSideWidth( nSide)) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 16) ; vdPar.emplace_back( 90) ; nSPar = 0 ; sPar.empty() ; return true ; } // se mezzo-legno if ( IS_LAP_JOINT( nGroup, nProc)) { vnDPar.reserve( 13) ; vdPar.reserve( 13) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 3) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0.5 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se scanalatura if ( IS_NOTCH( nGroup, nProc)) { vnDPar.reserve( 6) ; vdPar.reserve( 6) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; nSPar = 0 ; sPar.empty() ; return true ; } // se taglio per rivestimento if ( IS_SEATHING_CUT( nGroup, nProc)) { vnDPar.reserve( 3) ; vdPar.reserve( 3) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( GetSideLength( nSide)) ; nSPar = 0 ; sPar.empty() ; return true ; } // se foratura if ( IS_DRILL( nGroup, nProc)) { vnDPar.reserve( 7) ; vdPar.reserve( 7) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 3) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( GetSideHeight(nSide)) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; nSPar = 0 ; sPar.empty() ; return true ; } // se tenone if ( IS_TENON( nGroup, nProc)) { vnDPar.reserve( 12) ; vdPar.reserve( 12) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0.5 * GetSideWidth( nSide)) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 5) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se mortasa if ( IS_MORTISE( nGroup, nProc)) { vnDPar.reserve( 14) ; vdPar.reserve( 14) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0.5 * GetSideWidth( nSide)) ; vnDPar.emplace_back( 3) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 16) ; vdPar.emplace_back( 90) ; nSPar = 0 ; sPar.empty() ; return true ; } // se mortasa sul fronte if ( IS_MORTISE_FRONT( nGroup, nProc)) { vnDPar.reserve( 11) ; vdPar.reserve( 11) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0.5 * GetSideWidth( nSide)) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se testo if ( IS_TEXT( nGroup, nProc)) { vnDPar.reserve( 8) ; vdPar.reserve( 8) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; nSPar = 15 ; sPar.empty() ; return true ; } return false ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProcess( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, int nSPar, const DBLVECTOR& vdPar, const string& sPar) { // se taglio if ( IS_CUT( nGroup, nProc)) return AddCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se taglio longitudinale if ( IS_LONGIT_CUT( nGroup, nProc)) return AddLongitCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se doppio taglio if ( IS_DOUBLE_CUT( nGroup, nProc)) return AddDoubleCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se doppio taglio longitudinale if ( IS_RIDGEVALLEY_CUT( nGroup, nProc)) return AddRidgeValleyCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se mezzo-legno if ( IS_LAP_JOINT( nGroup, nProc)) return AddLapJoint( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se scanalatura if ( IS_NOTCH( nGroup, nProc)) return AddNotch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se taglio per rivestimento if ( IS_SEATHING_CUT( nGroup, nProc)) return AddSeathingCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se foratura if ( IS_DRILL( nGroup, nProc)) return AddDrill( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se tenone if ( IS_TENON( nGroup, nProc)) return AddTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se mortasa if ( IS_MORTISE( nGroup, nProc)) return AddMortise( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se mortasa sul fronte if ( IS_MORTISE_FRONT( nGroup, nProc)) return AddMortiseFront( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se testo if ( IS_TEXT( nGroup, nProc)) return AddText( nGroup, nProc, nSide, sDes, nProcId, vnDPar, nSPar, vdPar, sPar) ; return false ; } //---------------------------------------------------------------------------- bool BtlGeom::AddCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 5) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], vdPar[2]) ; double dAngle = Clamp( vdPar[3], 0.1, 179.9) ; double dInclination = Clamp( vdPar[4], 0.1, 179.9) ; // calcolo la normale alla faccia del taglio Vector3d vtN = FromSpherical( 1, 180 + dInclination, dAngle - 90) ; if ( nGroup == 1) vtN.Mirror( X_AX) ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; // creo la trimesh con questo contorno PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByFlatContour( plyCut.GetPolyLine())) return false ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLongitCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 8) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; int nLimits = lround( vdPar[2]) ; double dInclination = Clamp( vdPar[3], -90., 90.) ; double dStart = vdPar[0] ; double dLength = vdPar[5] ; // calcolo la normale alla faccia del taglio Vector3d vtN = FromSpherical( 1, dInclination, - 90) ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; // eventuali limiti longitudinali bool bStartLimited = false ; bool bEndLimited = false ; if ( dLength > EPS_SMALL) { if ( dStart > EPS_SMALL && ( nLimits == 0 || nLimits == 1 || nLimits == 5)) bStartLimited = true ; if ( ( dStart + dLength < m_vtDim.x - EPS_SMALL) && ( nLimits == 0 || nLimits == 1 || nLimits == 3)) bEndLimited = true ; } Polygon3d plyStart ; if ( bStartLimited) { // creo il poligono di inizio if ( ! CreatePolygonInBox( Point3d( dStart, 0, 0), X_AX, BTL_SIDE_NONE, plyStart)) return false ; // trimmo tra loro taglio e inizio if ( ! plyCut.Trim( plyStart, false, true) || ! plyStart.Trim( plyCut, false, false)) return false ; } Polygon3d plyEnd ; if ( bEndLimited) { // creo il poligono di fine if ( ! CreatePolygonInBox( Point3d( dStart + dLength, 0, 0), -X_AX, BTL_SIDE_NONE, plyEnd)) return false ; // trimmo tra loro taglio e fine if ( ! plyCut.Trim( plyEnd, false, true) || ! plyEnd.Trim( plyCut, false, false)) return false ; } // creo la trimesh dalle due facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyCut) || ! DoSewing( pStm, plyStart) || ! DoSewing( pStm, plyEnd)) return false ; pStm->DoCompacting() ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDoubleCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 6) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; double dAngle1 = Clamp( vdPar[2], 0.1, 179.9) ; double dInclination1 = Clamp( vdPar[3], 0.1, 179.9) ; double dAngle2 = Clamp( vdPar[4], 0.1, 179.9) ; double dInclination2 = Clamp( vdPar[5], 0.1, 179.9) ; // creo il primo poligono di taglio Polygon3d plyCut1 ; Vector3d vtN1 = FromSpherical( 1, 180 + dInclination1, dAngle1 - 90) ; if ( nGroup == 1) vtN1.Mirror( X_AX) ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyCut1)) return false ; // creo il secondo poligono di taglio Polygon3d plyCut2 ; Vector3d vtN2 = FromSpherical( 1, 180 + dInclination2, dAngle2 - 90) ; if ( nGroup == 1) vtN2.Mirror( X_AX) ; if ( ! CreatePolygonInBox( ptP, vtN2, nSide, plyCut2)) return false ; // trimmo tra loro le due facce bool bInVsOut = ( dAngle2 <= dAngle1) ; if ( ! plyCut1.Trim( plyCut2, bInVsOut, true) || ! plyCut2.Trim( plyCut1, bInVsOut, false)) return false ; // creo la trimesh dalle due facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyCut1) || ! DoSewing( pStm, plyCut2)) return false ; pStm->DoCompacting() ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddRidgeValleyCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 11) return false ; // sistemo i dati double dStart = vdPar[0] ; double dMid = vdPar[1] ; double dDepth = Clamp( vdPar[5], 0., 50000.) ; int nLimits = lround( vdPar[2]) ; double dInclination1 = Clamp( vdPar[3], -89.9, 89.9) ; double dInclination2 = Clamp( vdPar[4], -89.9, 89.9) ; double dLength = vdPar[6] ; Point3d ptP( dStart, dMid, - dDepth) ; // calcolo la prima faccia del taglio Polygon3d plyCut1 ; Vector3d vtN1 = FromSpherical( 1, dInclination1, - 90) ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyCut1)) return false ; // calcolo la seconda faccia del taglio Polygon3d plyCut2 ; Vector3d vtN2 = FromSpherical( 2, - dInclination2, - 90) ; if ( ! CreatePolygonInBox( ptP, vtN2, nSide, plyCut2)) return false ; // trimmo le facce tra loro bool bInVsOut = ( dInclination1 + dInclination2 >= 0) ; if ( ! plyCut1.Trim( plyCut2, bInVsOut, true) || ! plyCut2.Trim( plyCut1, bInVsOut, false)) return false ; // faccia longitudinale di servizio di separazione tra i tagli Polygon3d plyLong ; if ( ! CreatePolygonInBox( Point3d( 0, dMid, 0), - Y_AX, nSide, plyLong)) return false ; // eventuali limiti sulla lunghezza bool bStartLimited = false ; bool bEndLimited = false ; if ( dLength > EPS_SMALL) { if ( dStart > EPS_SMALL && ( nLimits == 0 || nLimits == 1 || nLimits == 5)) bStartLimited = true ; if ( ( dStart + dLength < m_vtDim.x - EPS_SMALL) && ( nLimits == 0 || nLimits == 1 || nLimits == 3)) bEndLimited = true ; } Polygon3d plyStart1, plyStart2 ; if ( bStartLimited) { // poligono di inizio per primo taglio if ( plyCut1.GetSideCount() > 0) { if ( ! CreatePolygonInBox( Point3d( dStart, 0, 0), X_AX, BTL_SIDE_NONE, plyStart1)) return false ; // lo limito solo se esiste anche il taglio 2 if ( plyCut2.GetSideCount() > 0) plyStart1.Trim( plyLong, false, false) ; if ( ! plyCut1.Trim( plyStart1, false, true) || ! plyStart1.Trim( plyCut1, false, false)) return false ; } // poligono di inizio per secondo taglio if ( plyCut2.GetSideCount() > 0) { if ( ! CreatePolygonInBox( Point3d( dStart, 0, 0), X_AX, BTL_SIDE_NONE, plyStart2)) return false ; // lo limito solo se esiste anche il taglio 1 if ( plyCut1.GetSideCount() > 0) plyStart2.Trim( plyLong, true, false) ; if ( ! plyCut2.Trim( plyStart2, false, true) || ! plyStart2.Trim( plyCut2, false, false)) return false ; } } Polygon3d plyEnd1, plyEnd2 ; if ( bEndLimited) { // poligono di fine per primo taglio if ( plyCut1.GetSideCount() > 0) { if ( ! CreatePolygonInBox( Point3d( dStart + dLength, 0, 0), -X_AX, BTL_SIDE_NONE, plyEnd1)) return false ; // lo limito solo se esiste anche il taglio 2 if ( plyCut2.GetSideCount() > 0) plyEnd1.Trim( plyLong, false, false) ; if ( ! plyCut1.Trim( plyEnd1, false, true) || ! plyEnd1.Trim( plyCut1, false, false)) return false ; } // poligono di fine per secondo taglio if ( plyCut2.GetSideCount() > 0) { if ( ! CreatePolygonInBox( Point3d( dStart + dLength, 0, 0), -X_AX, BTL_SIDE_NONE, plyEnd2)) return false ; // lo limito solo se esiste anche il taglio 1 if ( plyCut1.GetSideCount() > 0) plyEnd2.Trim( plyLong, true, false) ; if ( ! plyCut2.Trim( plyEnd2, false, true) || ! plyEnd2.Trim( plyCut2, false, false)) return false ; } } // creo la trimesh dalle diverse facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyCut1) || ! DoSewing( pStm, plyStart1) || ! DoSewing( pStm, plyEnd1) || ! DoSewing( pStm, plyCut2) || ! DoSewing( pStm, plyStart2) || ! DoSewing( pStm, plyEnd2)) return false ; pStm->DoCompacting() ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLapJoint( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 13) return false ; // sistemo i dati double dStartX = vdPar[0] ; double dStartY = vdPar[1] ; double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; int nFlag = int( vdPar[3]) ; double dAngle = Clamp( vdPar[4], 0.1, 179.9) ; double dInclination = Clamp( vdPar[5], 0.1, 179.9) ; double dSlope = Clamp( vdPar[6], -89.9, 89.9) ; double dLeadAngle = Clamp( vdPar[7], 0., 179.9) ; double dLeadIncl = Clamp( vdPar[8], 0., 179.9) ; double dDepth = vdPar[9] ; double dLength = Clamp( vdPar[10], 1., 99999.) ; double dWidth = ( ( vdPar[12] > EPS_SMALL) ? vdPar[12] : GetSideWidth( nSide) - dStartY) ; Point3d ptP( dStartX, dStartY, dStartZ) ; // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = FromSpherical( 1, 180 - dInclination, 90 - dAngle) ; if ( nGroup == 3) vtN1.Mirror( X_AX) ; if ( ( nGroup == 4 && (nFlag & 1) == 0) || ( nGroup == 3 && (nFlag & 2) == 0)) { if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyStart)) return false ; } // faccia di fine Polygon3d plyEnd ; if ( ( nGroup == 4 && (nFlag & 2) == 0) || ( nGroup == 3 && (nFlag & 1) == 0)) { if ( ! CreatePolygonInBox( ptP + dLength * vtN1, - vtN1, nSide, plyEnd)) return false ; } // normale alla faccia di fondo Vector3d vtN3 = FromSpherical( 1, 90 - dInclination, 90 - dAngle) ; Vector3d vtAx = FromSpherical( 1, 90, - 90 - dAngle) ; if ( nGroup == 3) { vtN3.Mirror( X_AX) ; vtAx.Mirror( X_AX) ; vtAx.Invert() ; } vtN3.Rotate( vtAx, dSlope) ; // facce davanti e dietro Polygon3d plyFront, plyBack ; if ( dLeadAngle < EPS_ANG_SMALL && dLeadIncl < EPS_ANG_SMALL) { // se esistono, sono parallele ai lati adiacenti al side if ( dStartY > EPS_SMALL) { if ( ! CreatePolygonInBox( ptP, Y_AX, nSide, plyFront)) return false ; } if ( dStartY + dWidth < GetSideWidth( nSide) - EPS_SMALL) { if ( ! CreatePolygonInBox( ptP + dWidth * Y_AX, - Y_AX, nSide, plyBack)) return false ; } } else { // sistemo eventuale default di angolo nullo if ( dLeadAngle < EPS_ANG_SMALL) dLeadAngle = ANG_RIGHT ; if ( dLeadIncl < EPS_ANG_SMALL) dLeadIncl = ANG_RIGHT ; // calcolo la normale alle facce davanti e dietro // vettore intersezione facce fondo e inizio Vector3d vtInt = vtN3 ^ vtN1 ; // ruoto questi vettori attorno alla normale del fondo di + e -dLeadAngle Vector3d vtRef1f = vtInt ; Vector3d vtRef1b = vtInt ; if ( (nFlag & 4) != 0) { vtRef1f.Rotate( vtN3, 180 - dLeadAngle) ; vtRef1b.Rotate( vtN3, 180 + dLeadAngle) ; } else { vtRef1f.Rotate( vtN3, dLeadAngle) ; vtRef1b.Rotate( vtN3, - dLeadAngle) ; } // ruoto questo vettore attorno alla normale dell'inizio di dLeadIncl Vector3d vtRef2 = vtInt ; if ( (nFlag & 4) != 0) vtRef2.Rotate( vtN1, 180 - dLeadIncl) ; else vtRef2.Rotate( vtN1, dLeadIncl) ; // la normale alla faccia davanti è perpendicolare a vtRef1f e vtRef2 Vector3d vtN2f = vtRef1f ^ vtRef2 ; vtN2f.Normalize() ; if ( nGroup == 3) vtN2f.Invert() ; // la normale alla faccia dietro è perpendicolare a vtRef1b e vtRef2 Vector3d vtN2b = vtRef1b ^ vtRef2 ; vtN2b.Normalize() ; if ( nGroup == 3) vtN2b.Invert() ; // calcolo la faccia davanti if ( (nFlag & 4) == 0) CreatePolygonInBox( ptP, vtN2f, nSide, plyFront) ; // calcolo la faccia dietro double dDeltaX = - dWidth * cos( dAngle * DEGTORAD) / sin( dAngle * DEGTORAD) ; if ( nGroup == 3) dDeltaX = - dDeltaX ; if ( (nFlag & 8) == 0) CreatePolygonInBox( ptP + dDeltaX * X_AX + dWidth * Y_AX, vtN2b, nSide, plyBack) ; } // trim tra queste facce if ( ! plyStart.Trim( plyFront, false, true) || ! plyFront.Trim( plyStart, false, false)) return false ; if ( ! plyStart.Trim( plyBack, false, true) || ! plyBack.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyFront, false, true) || ! plyFront.Trim( plyEnd, false, false)) return false ; if ( ! plyEnd.Trim( plyBack, false, true) || ! plyBack.Trim( plyEnd, false, false)) return false ; // faccia sopra Polygon3d plyTop ; if ( dStartZ < - EPS_SMALL && (nFlag & 32) == 0) { if ( ! CreatePolygonInBox( ptP, - vtN3, nSide, plyTop)) return false ; } // trim con le altre facce if ( ! plyStart.Trim( plyTop, false, true) || ! plyTop.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyTop, false, true) || ! plyTop.Trim( plyEnd, false, false)) return false ; if ( ! plyFront.Trim( plyTop, false, true) || ! plyTop.Trim( plyFront, false, false)) return false ; if ( ! plyBack.Trim( plyTop, false, true) || ! plyTop.Trim( plyBack, false, false)) return false ; // faccia di fondo Polygon3d plyBottom ; double dDist = dDepth / sin( dInclination * DEGTORAD) ; if ( (nFlag & 16) == 0) { if ( ! CreatePolygonInBox( ptP - dDist * vtN3, vtN3, nSide, plyBottom)) return false ; } // trim con le altre facce if ( ! plyStart.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyEnd, false, false)) return false ; if ( ! plyFront.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyFront, false, false)) return false ; if ( ! plyBack.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyBack, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyStart) ; DoSewing( pStm, plyEnd) ; DoSewing( pStm, plyFront) ; DoSewing( pStm, plyBack) ; DoSewing( pStm, plyTop) ; DoSewing( pStm, plyBottom) ; pStm->DoCompacting() ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddNotch( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 6) return false ; // sistemo i dati double dDepth = Clamp( vdPar[3], 0., 50000.) ; double dLength = Clamp( vdPar[4], 1., 99999.) ; double dWidth = Clamp( vdPar[5], 1., 50000.) ; Point3d ptP( vdPar[0], vdPar[1] - 0.5 * dWidth, 0.) ; // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( nGroup == 3) vtN1.Mirror( X_AX) ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ptP + dLength * vtN1, - vtN1, nSide, plyEnd)) return false ; // faccia davanti Polygon3d plyFront ; if ( ! CreatePolygonInBox( ptP, Y_AX, nSide, plyFront)) return false ; // faccia dietro Polygon3d plyBack ; if ( ! CreatePolygonInBox( ptP + dWidth * Y_AX, - Y_AX, nSide, plyBack)) return false ; // trim tra queste facce if ( ! plyStart.Trim( plyFront, false, true) || ! plyFront.Trim( plyStart, false, false)) return false ; if ( ! plyStart.Trim( plyBack, false, true) || ! plyBack.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyFront, false, true) || ! plyFront.Trim( plyEnd, false, false)) return false ; if ( ! plyEnd.Trim( plyBack, false, true) || ! plyBack.Trim( plyEnd, false, false)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - dDepth * Z_AX, Z_AX, nSide, plyBottom)) return false ; // trim con le altre facce if ( ! plyStart.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyEnd, false, false)) return false ; if ( ! plyFront.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyFront, false, false)) return false ; if ( ! plyBack.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyBack, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyStart) ; DoSewing( pStm, plyEnd) ; DoSewing( pStm, plyFront) ; DoSewing( pStm, plyBack) ; DoSewing( pStm, plyBottom) ; pStm->DoCompacting() ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddSeathingCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 3) return false ; // sistemo i dati Point3d ptP( vdPar[0], 0, 0) ; double dDepth = Clamp( vdPar[1], 0., GetSideHeight( nSide)) ; double dLength = Clamp( vdPar[2], 1., 99999.) ; // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( nGroup == 3) vtN1.Mirror( X_AX) ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ptP + dLength * vtN1, - vtN1, nSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - dDepth * Z_AX, Z_AX, nSide, plyBottom)) return false ; // trim tra le facce if ( ! plyStart.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyBottom, false, true) || ! plyBottom.Trim( plyEnd, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyStart) ; DoSewing( pStm, plyEnd) ; DoSewing( pStm, plyBottom) ; pStm->DoCompacting() ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDrill( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 7) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], - vdPar[2]) ; double dAngHor = Clamp( vdPar[3], 0., 360.) ; double dAngVert = Clamp( vdPar[4], 1., 179.) ; double dDepth = vdPar[5] / sin( dAngVert * DEGTORAD) ; double dRad = vdPar[6] / 2 ; // calcolo la direzione esterna del foro Vector3d vtN = Z_AX ; // foro su una delle facce laterali if ( abs( vdPar[2]) < EPS_SMALL) { if ( nGroup == 4) vtN = FromSpherical( 1, ANG_RIGHT - dAngVert, - dAngHor) ; else vtN = FromSpherical( 1, ANG_RIGHT - dAngVert, ANG_STRAIGHT - dAngHor) ; } // foro su una delle facce di testa else { if ( nGroup == 4) { vtN = FromSpherical( 1, ANG_RIGHT - dAngVert, dAngHor) ; vtN.Rotate( Y_AX, - ANG_RIGHT) ; } else { vtN = FromSpherical( 1, ANG_RIGHT - dAngVert, ANG_STRAIGHT + dAngHor) ; vtN.Rotate( Y_AX, ANG_RIGHT) ; } } // creo la circonferenza PtrOwner pArc( CreateCurveArc()) ; if ( IsNull( pArc)) return false ; // assegno i dati if ( ! pArc->Set( ptP, vtN, dRad)) return false ; pArc->SetExtrusion( vtN) ; pArc->SetThickness( - dDepth) ; // porto l'entità nel piano della faccia Frame3d frRef = GetSideFrame( nSide) ; pArc->ToGlob( frRef) ; // inserisco l'entità nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pArc)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddTenon( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 12) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; int nFlag = int( vdPar[2]) ; double dAngle = Clamp( vdPar[4], 0.1, 179.9) ; double dInclination = Clamp( vdPar[5], 0.1, 179.9) ; double dRot = Clamp( vdPar[6], 0.1, 179.9) ; double dFillet = vdPar[7] ; double dTenH = vdPar[8] ; double dTenW = vdPar[9] ; double dTenM1 = ( abs( vdPar[10]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[10]) ; double dTenM2 = ( abs( vdPar[11]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[11]) ; // calcolo la normale alla faccia del taglio Vector3d vtN = FromSpherical( 1, 180 + dInclination, dAngle - 90) ; if ( nGroup == 1) vtN.Mirror( X_AX) ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; // calcolo OCS Frame3d frTen ; frTen.Set( ptP, vtN, Z_AX ^ vtN) ; frTen.Rotate( ptP, vtN, ( nGroup != 1 ? 90 - dRot : dRot - 90)) ; frTen.ToGlob( GetSideFrame( nSide)) ; // lunghezza del tenone double dThick = GetSideHeight( nSide) ; double dCosA = frTen.VersY() * GetSideVersN( nSide) ; double dTenL = dThick / dCosA - dTenM1 - dTenM2 ; // calcolo il centro del tenone Point3d ptCen( 0, - dTenM1 - 0.5 * dTenL, 0) ; ptCen.ToGlob( frTen) ; // creo il contorno del tenone double dTenHW = 0.5 * dTenW ; PolyArc PA ; if ( nFlag == 1) { PA.AddUPoint( 0, Point3d( 0, - dTenM1, 0), 0) ; PA.AddUPoint( 1, Point3d( - dTenHW, - dTenM1, 0), 0) ; PA.AddUPoint( 2, Point3d( - dTenHW, - dTenM1 - dTenL, 0), 0) ; PA.AddUPoint( 3, Point3d( dTenHW, - dTenM1 - dTenL, 0), 0) ; PA.AddUPoint( 4, Point3d( dTenHW, - dTenM1, 0), 0) ; PA.Close() ; } else { const double BULGE_90D = tan( 90.0 / 4 * DEGTORAD) ; double dRad = 0.5 * min( dTenW, dTenL) ; if ( nFlag == 0 || nFlag == 3) dRad = min( dRad, MILL_DEF_RAD) ; else if ( nFlag == 4) dRad = min( dRad, dFillet) ; PA.AddUPoint( 0, Point3d( - dTenHW + dRad, - dTenM1, 0), BULGE_90D) ; PA.AddUPoint( 1, Point3d( - dTenHW, - dTenM1 - dRad, 0), 0) ; PA.AddUPoint( 2, Point3d( - dTenHW, - dTenM1 - dTenL + dRad, 0), BULGE_90D) ; PA.AddUPoint( 3, Point3d( - dTenHW + dRad, - dTenM1 - dTenL, 0), 0) ; PA.AddUPoint( 4, Point3d( dTenHW - dRad, - dTenM1 - dTenL, 0), BULGE_90D) ; PA.AddUPoint( 5, Point3d( dTenHW, - dTenM1 - dTenL + dRad, 0), 0) ; PA.AddUPoint( 6, Point3d( dTenHW, - dTenM1 - dRad, 0), BULGE_90D) ; PA.AddUPoint( 7, Point3d( dTenHW - dRad, - dTenM1, 0), 0) ; PA.Close() ; } PtrOwner pCrvTen( CreateCurveComposite()) ; if ( IsNull( pCrvTen) || ! pCrvTen->FromPolyArc( PA)) return false ; pCrvTen->MergeCurves( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG) ; pCrvTen->SetExtrusion( Z_AX) ; pCrvTen->ToGlob( frTen) ; // lo approssimo con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL ; if ( ! pCrvTen->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( frTen.VersZ()) ; // creo la regione del contorno esterno PtrOwner pExt( CreateCurveComposite()) ; if ( IsNull( pExt) || ! pExt->FromPolyLine( plyCut.GetPolyLine())) return false ; SurfFlatRegionByContours SfrExt ; SfrExt.AddCurve( Release( pExt)) ; PtrOwner pReg( SfrExt.GetSurf()) ; if ( IsNull( pReg)) return false ; // creo la regione del tenone SurfFlatRegionByContours SfrTen ; SfrTen.AddCurve( pCompo->Clone()) ; PtrOwner pTen( SfrTen.GetSurf()) ; if ( IsNull( pTen)) return false ; // sottraggo la regione del tenone da quella esterna if ( ! pReg->Subtract( *pTen)) return false ; // ne deduco la superficie trimesh PtrOwner pStm( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStm)) return false ; // creo la superficie trimesh del tenone PtrOwner pStmTen( CreateSurfTriMesh()) ; if ( IsNull( pStmTen) || ! pStmTen->CreateByExtrusion( PL, frTen.VersZ() * dTenH)) return false ; pStm->DoSewing( *pStmTen) ; // creo la superficie trimesh di testa del tenone PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL)) return false ; pStmCap->Translate( frTen.VersZ() * dTenH) ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_LEFT ; ++ i) { Plane3d plFace = GetSidePlane( i) ; pStm->Cut( plFace, true) ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvTen)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddMortise( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 13) return false ; // sistemo i dati double dStartX = vdPar[0] ; double dStartY = vdPar[1] ; double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; int nFlag = int( vdPar[3]) ; double dAngle = Clamp( vdPar[4], -180.0, 180.0) ; double dSideIncl = Clamp( vdPar[6], 0.1, 179.9) ; double dFrontIncl = Clamp( vdPar[13], 0.1, 179.9) ; double dFillet = vdPar[7] ; double dMortD = vdPar[8] ; double dMortW = vdPar[9] ; double dStrutAng = Clamp( vdPar[5], 0.1, 179.9) ; double dMortM1 = vdPar[11] ; double dMortM2 = vdPar[12] ; double dMortL = Clamp( vdPar[10] / sin( dStrutAng * DEGTORAD) - dMortM1 - dMortM2, 1., 99999.) ; Point3d ptP( dStartX, dStartY, dStartZ) ; // calcolo la normale alla faccia di fondo Vector3d vtN1 = FromSpherical( 1, 180 - dFrontIncl, dAngle) ; if ( nGroup == 3) vtN1.Mirror( X_AX) ; double dSideAng = ( nGroup != 3 ? dSideIncl : 180 - dSideIncl) ; Vector3d vtN2 = FromSpherical( 1, dSideAng, ANG_RIGHT + dAngle) ; if ( nGroup == 3) vtN2.Mirror( X_AX) ; Vector3d vtN3 = vtN1 ^ vtN2 ; if ( nGroup == 3) vtN3.Invert() ; // calcolo riferimento della faccia di fondo Frame3d frMort ; frMort.Set( ptP - dMortD * vtN3, vtN3, vtN2) ; frMort.ToGlob( GetSideFrame( nSide)) ; // calcolo il centro della mortasa Point3d ptCen( 0, - dMortM1 - 0.5 * dMortL, 0) ; ptCen.ToGlob( frMort) ; // creo il contorno della mortasa double dMortHW = 0.5 * dMortW ; PolyArc PA ; if ( nFlag == 1) { PA.AddUPoint( 0, Point3d( 0, - dMortM1, 0), 0) ; PA.AddUPoint( 1, Point3d( - dMortHW, - dMortM1, 0), 0) ; PA.AddUPoint( 2, Point3d( - dMortHW, - dMortM1 - dMortL, 0), 0) ; PA.AddUPoint( 3, Point3d( dMortHW, - dMortM1 - dMortL, 0), 0) ; PA.AddUPoint( 4, Point3d( dMortHW, - dMortM1, 0), 0) ; PA.Close() ; } else { const double BULGE_90D = tan( ANG_RIGHT / 4 * DEGTORAD) ; double dRad = 0.5 * min( dMortW, dMortL) ; if ( nFlag == 0 || nFlag == 3) dRad = min( dRad, MILL_DEF_RAD) ; else if ( nFlag == 4) dRad = min( dRad, dFillet) ; PA.AddUPoint( 0, Point3d( - dMortHW + dRad, - dMortM1, 0), BULGE_90D) ; PA.AddUPoint( 1, Point3d( - dMortHW, - dMortM1 - dRad, 0), 0) ; PA.AddUPoint( 2, Point3d( - dMortHW, - dMortM1 - dMortL + dRad, 0), BULGE_90D) ; PA.AddUPoint( 3, Point3d( - dMortHW + dRad, - dMortM1 - dMortL, 0), 0) ; PA.AddUPoint( 4, Point3d( dMortHW - dRad, - dMortM1 - dMortL, 0), BULGE_90D) ; PA.AddUPoint( 5, Point3d( dMortHW, - dMortM1 - dMortL + dRad, 0), 0) ; PA.AddUPoint( 6, Point3d( dMortHW, - dMortM1 - dRad, 0), BULGE_90D) ; PA.AddUPoint( 7, Point3d( dMortHW - dRad, - dMortM1, 0), 0) ; PA.Close() ; } PtrOwner pCrvMort( CreateCurveComposite()) ; if ( IsNull( pCrvMort) || ! pCrvMort->FromPolyArc( PA)) return false ; pCrvMort->SetExtrusion( Z_AX) ; pCrvMort->ToGlob( frMort) ; // lo approssimo con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL ; if ( ! pCrvMort->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( frMort.VersZ()) ; // creo la superficie trimesh di fondo della mortasa PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByPointCurve( ptCen, PL)) return false ; // creo la superficie trimesh laterale della mortasa double dExtr = dMortD + ( dMortM1 + dMortL) * max( tan( ( ANG_RIGHT - dFrontIncl) * DEGTORAD), 0.) + dMortHW * abs( tan( ( ANG_RIGHT - dSideIncl) * DEGTORAD)) ; if ( abs( ANG_RIGHT - dFrontIncl) > EPS_ANG_SMALL || abs( ANG_RIGHT - dSideIncl) > EPS_ANG_SMALL) dExtr += 50.0 ; PtrOwner pStmMort( CreateSurfTriMesh()) ; if ( IsNull( pStmMort) || ! pStmMort->CreateByExtrusion( PL, frMort.VersZ() * dExtr)) return false ; pStmMort->Invert() ; pStm->DoSewing( *pStmMort) ; // eseguo trim con le facce della trave for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_LEFT ; ++ i) { Plane3d plFace = GetSidePlane( i) ; pStm->Cut( plFace, true) ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // inserisco la curva nel DB geometrico int nMId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvMort)) ; if ( nMId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddMortiseFront( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 11) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; int nFlag = int( vdPar[2]) ; double dAngle = Clamp( vdPar[3], 0.1, 179.9) ; double dInclination = Clamp( vdPar[4], 0.1, 179.9) ; double dRot = Clamp( vdPar[5], 0.1, 179.9) ; double dFillet = vdPar[6] ; double dMortD = vdPar[7] ; double dMortW = vdPar[8] ; double dMortM1 = ( abs( vdPar[9]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[9]) ; double dMortM2 = ( abs( vdPar[10]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[10]) ; // calcolo la normale alla faccia del taglio Vector3d vtN = FromSpherical( 1, 180 + dInclination, dAngle - 90) ; if ( nGroup == 3) vtN.Mirror( X_AX) ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; // calcolo OCS Frame3d frMort ; frMort.Set( ptP, vtN, Z_AX ^ vtN) ; frMort.Rotate( ptP, vtN, ( nGroup != 3 ? 90 - dRot : dRot - 90)) ; frMort.ToGlob( GetSideFrame( nSide)) ; // lunghezza della mortasa double dThick = GetSideHeight( nSide) ; double dCosA = frMort.VersY() * GetSideVersN( nSide) ; double dMortL = dThick / dCosA - dMortM1 - dMortM2 ; // calcolo il centro della mortasa Point3d ptCen( 0, - dMortM1 - 0.5 * dMortL, 0) ; ptCen.ToGlob( frMort) ; // creo il contorno della mortasa double dMortHW = 0.5 * dMortW ; PolyArc PA ; if ( nFlag == 1) { PA.AddUPoint( 0, Point3d( 0, - dMortM1, 0), 0) ; PA.AddUPoint( 1, Point3d( - dMortHW, - dMortM1, 0), 0) ; PA.AddUPoint( 2, Point3d( - dMortHW, - dMortM1 - dMortL, 0), 0) ; PA.AddUPoint( 3, Point3d( dMortHW, - dMortM1 - dMortL, 0), 0) ; PA.AddUPoint( 4, Point3d( dMortHW, - dMortM1, 0), 0) ; PA.Close() ; } else { const double BULGE_90D = tan( 90.0 / 4 * DEGTORAD) ; double dRad = 0.5 * min( dMortW, dMortL) ; if ( nFlag == 0 || nFlag == 3) dRad = min( dRad, MILL_DEF_RAD) ; else if ( nFlag == 4) dRad = min( dRad, dFillet) ; PA.AddUPoint( 0, Point3d( - dMortHW + dRad, - dMortM1, 0), BULGE_90D) ; PA.AddUPoint( 1, Point3d( - dMortHW, - dMortM1 - dRad, 0), 0) ; PA.AddUPoint( 2, Point3d( - dMortHW, - dMortM1 - dMortL + dRad, 0), BULGE_90D) ; PA.AddUPoint( 3, Point3d( - dMortHW + dRad, - dMortM1 - dMortL, 0), 0) ; PA.AddUPoint( 4, Point3d( dMortHW - dRad, - dMortM1 - dMortL, 0), BULGE_90D) ; PA.AddUPoint( 5, Point3d( dMortHW, - dMortM1 - dMortL + dRad, 0), 0) ; PA.AddUPoint( 6, Point3d( dMortHW, - dMortM1 - dRad, 0), BULGE_90D) ; PA.AddUPoint( 7, Point3d( dMortHW - dRad, - dMortM1, 0), 0) ; PA.Close() ; } PtrOwner pCrvTen( CreateCurveComposite()) ; if ( IsNull( pCrvTen) || ! pCrvTen->FromPolyArc( PA)) return false ; pCrvTen->SetExtrusion( Z_AX) ; pCrvTen->ToGlob( frMort) ; // lo approssimo con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL ; if ( ! pCrvTen->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( frMort.VersZ()) ; // creo la regione del contorno esterno PtrOwner pExt( CreateCurveComposite()) ; if ( IsNull( pExt) || ! pExt->FromPolyLine( plyCut.GetPolyLine())) return false ; SurfFlatRegionByContours SfrExt ; SfrExt.AddCurve( Release( pExt)) ; PtrOwner pReg( SfrExt.GetSurf()) ; if ( IsNull( pReg)) return false ; // creo la regione del tenone SurfFlatRegionByContours SfrTen ; SfrTen.AddCurve( pCompo->Clone()) ; PtrOwner pTen( SfrTen.GetSurf()) ; if ( IsNull( pTen)) return false ; // sottraggo la regione del tenone da quella esterna if ( ! pReg->Subtract( *pTen)) return false ; // ne deduco la superficie trimesh PtrOwner pStm( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStm)) return false ; // creo la superficie trimesh della mortasa PtrOwner pStmTen( CreateSurfTriMesh()) ; if ( IsNull( pStmTen) || ! pStmTen->CreateByExtrusion( PL, - frMort.VersZ() * dMortD)) return false ; pStm->DoSewing( *pStmTen) ; // creo la superficie trimesh di fondo della mortasa PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL)) //if ( IsNull( pStmCap) || ! pStmCap->CreateByFlatContour( PL)) return false ; pStmCap->Translate( - frMort.VersZ() * dMortD) ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_LEFT ; ++ i) { Plane3d plFace = GetSidePlane( i) ; pStm->Cut( plFace, true) ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvTen)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddText( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, int nSPar, const DBLVECTOR& vdPar, const string& sPar) { // verifica dei parametri if ( vdPar.size() < 8 || sPar.empty()) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; Vector3d vtD = FromPolar( 1, vdPar[2]) ; double dH = vdPar[7] ; int nInsPos ; switch ( lround( vdPar[3])) { case 0 : switch ( lround( vdPar[4])) { case 0 : nInsPos = ETXT_IPBL ; break ; case 1 : nInsPos = ETXT_IPBC ; break ; case 2 : nInsPos = ETXT_IPBR ; break ; } break ; case 1 : switch ( lround( vdPar[4])) { case 0 : nInsPos = ETXT_IPML ; break ; case 1 : nInsPos = ETXT_IPMC ; break ; case 2 : nInsPos = ETXT_IPMR ; break ; } break ; case 2 : switch ( lround( vdPar[4])) { case 0 : nInsPos = ETXT_IPTL ; break ; case 1 : nInsPos = ETXT_IPTC ; break ; case 2 : nInsPos = ETXT_IPTR ; break ; } break ; } // non è gestito P11 (giustificazione su multilinea) // assegno il testo string sText ; if ( lround( vdPar[6]) == 0) sText = sPar ; // rotazione dei caratteri di 90 gradi else { // ruoto la direzione di riferimento vtD.Rotate( Z_AX, 90) ; // inserisco un a capo dopo ogni carattere, tranne l'ultimo size_t nChar = sPar.size() ; for ( size_t i = 0 ; i < nChar - 1 ; ++ i) sText += sPar[i] + ETXT_LINEBREAK ; sText += sPar[nChar-1] ; // sistemo il tipo di inserimento switch ( nInsPos) { case ETXT_IPTL : nInsPos = ETXT_IPTR ; break ; case ETXT_IPTC : nInsPos = ETXT_IPMR ; break ; case ETXT_IPTR : nInsPos = ETXT_IPBR ; break ; case ETXT_IPML : nInsPos = ETXT_IPTC ; break ; case ETXT_IPMC : break ; case ETXT_IPMR : nInsPos = ETXT_IPBC ; break ; case ETXT_IPBL : nInsPos = ETXT_IPTL ; break ; case ETXT_IPBC : nInsPos = ETXT_IPML ; break ; case ETXT_IPBR : nInsPos = ETXT_IPBL ; break ; } } // creo il testo PtrOwner pText( CreateExtText()) ; if ( IsNull( pText)) return false ; // assegno i dati if ( ! pText->Set( ptP, Z_AX, vtD, sText, "", 100, false, dH, 1, 0, nInsPos)) return false ; // porto il testo nel piano della faccia Frame3d frRef = GetSideFrame( nSide) ; pText->ToGlob( frRef) ; // inserisco il testo nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pText)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; string sKey = IKEY_PAR + ToString( nSPar, 2) ; m_pGDB->SetInfo( nId, sKey, sPar) ; // colore per linee di marcatura e testi m_pGDB->SetMaterial( nId, m_MarkCol) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::CreatePolygonInBox( const Point3d& ptP, const Vector3d& vtN, int nSide, Polygon3d& Polyg) { // calcolo il piano Plane3d plPlane ; if ( ! SetPlane( ptP, vtN, plPlane)) return false ; // trasformo il piano per faccia di inserimento if ( nSide != BTL_SIDE_NONE) { Frame3d frRef = GetSideFrame( nSide) ; plPlane.ToGlob( frRef) ; } // creo il poligono, limitandolo al box dell'oggetto (trave/parete) return Polyg.FromPlaneTrimmedWithBox( plPlane, ORIG, ORIG + m_vtDim) ; } //---------------------------------------------------------------------------- bool BtlGeom::DoSewing( ISurfTriMesh* pStm, const Polygon3d& Polyg) { // verifico esistenza superficie if ( pStm == nullptr) return false ; // se poligono vuoto, non devo fare alcunché if ( Polyg.GetSideCount() == 0) return true ; // creo la superficie trimesh del poligono PtrOwner pStm2( CreateSurfTriMesh()) ; if ( IsNull( pStm2) || ! pStm2->CreateByFlatContour( Polyg.GetPolyLine())) return false ; // le unisco return pStm->DoSewing( *pStm2) ; } //--------------------------------------------------------------------------- bool BtlGeom::SetNameAndInfo( int nId, int nGroup, int nProc, int nSide, const string& sDes, int nProcId) { if ( nId == GDB_ID_NULL) return false ; // nome string sName ; if ( nProcId >= 0) sName = ToString( nProcId) ; if ( ! sDes.empty()) sName += "-" + sDes ; m_pGDB->SetName( nId, sName) ; // info con tipo m_pGDB->SetInfo( nId, IKEY_GROUP, nGroup) ; m_pGDB->SetInfo( nId, IKEY_PROC, nProc) ; m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ; return true ; } //--------------------------------------------------------------------------- bool BtlGeom::SetParams( int nId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { if ( nId == GDB_ID_NULL) return false ; // elenco dei parametri size_t nNumPar = min( vnDPar.size(), vdPar.size()) ; for ( size_t i = 0 ; i < nNumPar ; ++ i) { string sKey = IKEY_PAR + ToString( vnDPar[i], 2) ; m_pGDB->SetInfo( nId, sKey, vdPar[i]) ; } return true ; }