//---------------------------------------------------------------------------- // EgalTech 2015-2017 //---------------------------------------------------------------------------- // File : BtlGeomProc.cpp Data : 15.05.17 Versione : 1.8e3 // 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. // 20.03.17 DS Agg. import tenoni e mortase a coda di rondine. // 15.05.17 DS Agg. import Profile Head Cambered. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DllMain.h" #include "BtlGeom.h" #include "Polygon3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EgkArcSpecial.h" #include "/EgtDev/Include/EGkCurveBezier.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/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/ENkPolynomialRoots.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_SLOT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 16) #define IS_FRONT_SLOT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 17) #define IS_BIRDS_MOUTH( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 20) #define IS_RIDGE_LAP( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 30) #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_CHAMFER( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 36) #define IS_POCKET( nG, nP) ( ( nGroup == 4) && nProc == 39) #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_HOUSE( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 52) #define IS_HOUSE_MORTISE( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 53) #define IS_DOVETAIL_TENON( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 55) #define IS_DOVETAIL_MORTISE( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 55) #define IS_DTMORTISE_FRONT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 56) #define IS_MARKING( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 60) #define IS_TEXT( nG, nP) ( ( nGroup == 4) && nProc == 61) #define IS_SIMPLESCARF( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 70) #define IS_SCARFJOINT( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 71) #define IS_STEPJOINT( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 80) #define IS_STEPJOINTNOTCH( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 80) #define IS_PROF_HEADCONCAVE( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 101) #define IS_PROF_HEADCONVEX( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 102) #define IS_PROF_HEADCAMBERED( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 103) #define IS_ROUND_ARCH( nG, nP) ( ( nGroup == 4) && nProc == 104) #define IS_FREE_CONTOUR( nG, nP) ( ( nGroup == 0 || nGroup == 3 || nGroup == 4) && nProc == 250) //---------------------------------------------------------------------------- const double COS_ALMOST_PERP = cos( 85. * DEGTORAD) ; const double LEN_EXTRUS_AGG = 50. ; //---------------------------------------------------------------------------- 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 scanalatura if ( IS_SLOT( nGroup, nProc)) { vnDPar.reserve( 14) ; vdPar.reserve( 14) ; 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( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 200) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se scanalatura frontale if ( IS_FRONT_SLOT( nGroup, nProc)) { vnDPar.reserve( 9) ; vdPar.reserve( 9) ; 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) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 40) ; nSPar = 0 ; sPar.empty() ; return true ; } // se tacca if ( IS_BIRDS_MOUTH( 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( 5) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 135) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; 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( 0) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se mezzo-legno di testa if ( IS_RIDGE_LAP( 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( 6) ; vdPar.emplace_back( 90) ; 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) ; 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 intaglio 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 smusso if ( IS_CHAMFER( nGroup, nProc)) { vnDPar.reserve( 5) ; vdPar.reserve( 5) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( GetSideLength( nSide)) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se tasca if ( IS_POCKET( nGroup, nProc)) { vnDPar.reserve( 10) ; vdPar.reserve( 10) ; 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( 6) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 20) ; 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 avanzamento tenone if ( IS_HOUSE( nGroup, nProc)) { vnDPar.reserve( 13) ; vdPar.reserve( 13) ; 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) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se avanzamento mortasa if ( IS_HOUSE_MORTISE( nGroup, nProc)) { vnDPar.reserve( 15) ; vdPar.reserve( 15) ; 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) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se tenone a coda di rondine if ( IS_DOVETAIL_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( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 28) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se mortasa a coda di rondine if ( IS_DOVETAIL_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( 5) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 28) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se mortasa a coda di rondine sul fronte if ( IS_DTMORTISE_FRONT( 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( 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( 9) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 28) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se marcatura if ( IS_MARKING( 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( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; nSPar = 15 ; 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 ; } // se giunto gerber if ( IS_SIMPLESCARF( nGroup, nProc)) { vnDPar.reserve( 6) ; vdPar.reserve( 6) ; vnDPar.emplace_back( 1) ; 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) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se giunto a dardo if ( IS_SCARFJOINT( nGroup, nProc)) { vnDPar.reserve( 9) ; vdPar.reserve( 9) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se incastro dietro if ( IS_STEPJOINT( nGroup, nProc)) { vnDPar.reserve( 7) ; vdPar.reserve( 7) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se incastro semplice if ( IS_STEPJOINTNOTCH( nGroup, nProc)) { vnDPar.reserve( 10) ; vdPar.reserve( 10) ; 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( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( GetSideWidth( nSide)) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 200) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } // se profilo concavo if ( IS_PROF_HEADCONCAVE( nGroup, nProc)) { vnDPar.reserve( 6) ; vdPar.reserve( 6) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 120) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 20) ; nSPar = 0 ; sPar.empty() ; return true ; } // se profilo convesso if ( IS_PROF_HEADCONVEX( nGroup, nProc)) { vnDPar.reserve( 6) ; vdPar.reserve( 6) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 120) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 20) ; nSPar = 0 ; sPar.empty() ; return true ; } // se profilo caudato if ( IS_PROF_HEADCAMBERED( nGroup, nProc)) { vnDPar.reserve( 7) ; vdPar.reserve( 7) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 500) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 60) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 40) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 1) ; nSPar = 0 ; sPar.empty() ; return true ; } // se arco if ( IS_ROUND_ARCH( nGroup, nProc)) { vnDPar.reserve( 3) ; vdPar.reserve( 3) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 30) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 500) ; nSPar = 0 ; sPar.empty() ; return true ; } // se contorno libero if ( IS_FREE_CONTOUR( nGroup, nProc)) { vnDPar.reserve( 11) ; vdPar.reserve( 11) ; 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( 5) ; vdPar.emplace_back( GetSideHeight( nSide)) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 0) ; 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) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.empty() ; return true ; } return false ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProcess( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, int nSPar, const DBLVECTOR& vdPar, const string& sPar, int nLine) { // salvo numero di linea del file in cui è definito il processo m_nBtlLine = nLine ; // 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 scanalatura if ( IS_SLOT( nGroup, nProc)) return AddSlot( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se scanalatura frontale if ( IS_FRONT_SLOT( nGroup, nProc)) return AddFrontSlot( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se tacca if ( IS_BIRDS_MOUTH( nGroup, nProc)) return AddBirdsMouth( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se mezzo-legno di testa if ( IS_RIDGE_LAP( nGroup, nProc)) return AddRidgeLap( 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 intaglio 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 smusso if ( IS_CHAMFER( nGroup, nProc)) return AddChamfer( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se tasca if ( IS_POCKET( nGroup, nProc)) return AddPocket( 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 avanzamento tenone if ( IS_HOUSE( nGroup, nProc)) { nGroup = ( nGroup == 3 ? 1 : 2) ; return AddTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; } // se avanzamento mortasa if ( IS_HOUSE_MORTISE( nGroup, nProc)) return AddMortise( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se tenone a coda di rondine if ( IS_DOVETAIL_TENON( nGroup, nProc)) return AddDovetailTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se mortasa a coda di rondine if ( IS_DOVETAIL_MORTISE( nGroup, nProc)) return AddDovetailMortise( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se mortasa a coda di rondine sul fronte if ( IS_DTMORTISE_FRONT( nGroup, nProc)) return AddDtMortiseFront( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se marcatura if ( IS_MARKING( nGroup, nProc)) return AddMarking( nGroup, nProc, nSide, sDes, nProcId, vnDPar, nSPar, vdPar, sPar) ; // se testo if ( IS_TEXT( nGroup, nProc)) return AddText( nGroup, nProc, nSide, sDes, nProcId, vnDPar, nSPar, vdPar, sPar) ; // se giunto gerber if ( IS_SIMPLESCARF( nGroup, nProc)) return AddSimpleScarf( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se giunto a dardo if ( IS_SCARFJOINT( nGroup, nProc)) return AddScarfJoint( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // incastro dietro if ( IS_STEPJOINT( nGroup, nProc)) return AddStepJoint( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se incastro semplice if ( IS_STEPJOINTNOTCH( nGroup, nProc)) return AddStepJointNotch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se profilo concavo if ( IS_PROF_HEADCONCAVE( nGroup, nProc)) return AddProfileHeadCoCo( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se profilo convesso if ( IS_PROF_HEADCONVEX( nGroup, nProc)) return AddProfileHeadCoCo( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se profilo caudato if ( IS_PROF_HEADCAMBERED( nGroup, nProc)) return AddProfileHeadCambered( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se arco if ( IS_ROUND_ARCH( nGroup, nProc)) return AddRoundArch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar) ; // se contorno libero if ( IS_FREE_CONTOUR( nGroup, nProc)) return AddFreeContour( nGroup, nProc, nSide, sDes, nProcId, frRef, 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 ; // colore semitrasparente //SetAlpha( nId, 80) ; // 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 ; // colore semitrasparente //SetAlpha( nId, 80) ; // 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], -50000., 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::AddSlot( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 14) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], -vdPar[2]) ; // P01, P02, P03 int nFlag = lround( vdPar[3]) ; // P04 double dAngle = Clamp( vdPar[4], -90., 90.9) ; // P06 double dInclination = Clamp( vdPar[5], 0.1, 179.9) ; // P07 double dIntAngRef = Clamp( vdPar[6], 0.1, 179.9) ; // P08 double dIntAngOpp = Clamp( vdPar[7], 0.1, 179.9) ; // P09 double dAddAngOpp = Clamp( vdPar[8], 0.1-dIntAngOpp, 179.9-dIntAngOpp) ; // P10 double dDepth = Clamp( vdPar[9], 1., 50000.) ; // P11 double dLength = Clamp( vdPar[10], 1., 100000.) ; // P12 double dThick = Clamp( vdPar[11], 1., 50000.) ; // P13 double dDispEntRef = Clamp( vdPar[12], 0., 50000.) ; // P14 double dDispEntOpp = Clamp( vdPar[13], 0., 50000.) ; // P15 // costruzione delle normali delle facce double dAngEff = ( nGroup == 4 ? dAngle : ANG_STRAIGHT - dAngle) ; double dInclEff = ( nGroup == 4 ? dInclination : ANG_STRAIGHT - dInclination) ; Vector3d vtN1 = Z_AX ; vtN1.Rotate( Y_AX, dIntAngRef) ; Vector3d vtN3 = - vtN1 ; vtN3.Rotate( Y_AX, dAddAngOpp) ; Vector3d vtNf = vtN1 ; vtNf.Rotate( Y_AX, - dIntAngOpp) ; vtNf.Rotate( X_AX, dInclEff - 90) ; Vector3d vtN2 = - Z_AX ; vtN2.Rotate( X_AX, dInclEff) ; Vector3d vtN4 = - vtN2 ; vtN1.Rotate( Z_AX, dAngEff) ; vtN2.Rotate( Z_AX, dAngEff) ; vtN3.Rotate( Z_AX, dAngEff) ; vtN4.Rotate( Z_AX, dAngEff) ; vtNf.Rotate( Z_AX, dAngEff) ; // costruzione dei vettori edge faccia 1 Vector3d vtEv = vtN1 ^ vtN2 ; vtEv.Normalize() ; Vector3d vtEo = vtN1 ^ vtNf ; vtEo.Normalize() ; double dCoeff = vtEv.z ; // se caso frontale if ( abs( ptP.z) > EPS_SMALL) { double dRotAng = ( nGroup == 4 ? - ANG_RIGHT : ANG_RIGHT) ; vtN1.Rotate( Y_AX, dRotAng) ; vtN2.Rotate( Y_AX, dRotAng) ; vtN3.Rotate( Y_AX, dRotAng) ; vtN4.Rotate( Y_AX, dRotAng) ; vtNf.Rotate( Y_AX, dRotAng) ; vtEv.Rotate( Y_AX, dRotAng) ; vtEo.Rotate( Y_AX, dRotAng) ; } // calcolo del punto sul fondo Point3d ptB = ptP - vtEv * ( dDepth / dCoeff) ; // facce Polygon3d plyFaceF ; if ( ! CreatePolygonInBox( ptB, vtNf, nSide, plyFaceF)) return false ; Polygon3d plyFace1 ; if ( ! CreatePolygonInBox( ptB, vtN1, nSide, plyFace1)) return false ; Polygon3d plyFace2 ; if ( ! CreatePolygonInBox( ptB + vtEo * dThick / 2, vtN2, nSide, plyFace2)) return false ; Polygon3d plyFace3 ; if ( ! CreatePolygonInBox( ptB + vtN1 * dLength, vtN3, nSide, plyFace3)) return false ; Polygon3d plyFace4 ; if ( ! CreatePolygonInBox( ptB - vtEo * dThick / 2, vtN4, nSide, plyFace4)) return false ; // trimmo tra loro le facce if ( ! TrimPolygons( plyFaceF, plyFace1, false, false) || ! TrimPolygons( plyFaceF, plyFace2, false, false) || ! TrimPolygons( plyFaceF, plyFace3, false, false) || ! TrimPolygons( plyFaceF, plyFace4, false, false)) return false ; if ( ! TrimPolygons( plyFace1, plyFace2, false, false) || ! TrimPolygons( plyFace2, plyFace3, false, false) || ! TrimPolygons( plyFace3, plyFace4, false, false) || ! TrimPolygons( plyFace4, plyFace1, false, false)) return false ; // creo la trimesh dalle facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyFaceF) || ! DoSewing( pStm, plyFace1) || ! DoSewing( pStm, plyFace2) || ! DoSewing( pStm, plyFace3) || ! DoSewing( pStm, plyFace4)) 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::AddFrontSlot( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 9) 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) ; double dRot = Clamp( vdPar[5], 0., 360.) ; double dMortD = Clamp( vdPar[6], 0., 50000.) ; double dMortL = Clamp( vdPar[7], 0., 50000.) ; double dMortW = Clamp( vdPar[8], 0., 50000.) ; // 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)) ; // creo il contorno della mortasa double dMortHL = 0.5 * dMortL ; double dMortHW = 0.5 * dMortW ; PolyLine PL ; PL.AddUPoint( 0, Point3d( 0, dMortHL, 0)) ; PL.AddUPoint( 1, Point3d( - dMortHW, dMortHL, 0)) ; PL.AddUPoint( 2, Point3d( - dMortHW, - dMortHL, 0)) ; PL.AddUPoint( 3, Point3d( dMortHW, - dMortHL, 0)) ; PL.AddUPoint( 4, Point3d( dMortHW, dMortHL, 0)) ; PL.Close() ; PL.ToGlob( frMort) ; PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( frMort.VersZ()) ; // definisco la superficie PtrOwner pStm ; // creo la regione del contorno esterno PtrOwner pExt( CreateCurveComposite()) ; if ( IsNull( pExt)) return false ; if ( pExt->FromPolyLine( plyCut.GetPolyLine())) { 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 pStm.Set( 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 ; if ( IsNull( pStm)) pStm.Set( Release( pStmTen)) ; else pStm->DoSewing( *pStmTen) ; // creo la superficie trimesh di fondo della mortasa PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( frMort.Orig(), PL)) return false ; pStmCap->Translate( - frMort.VersZ() * dMortD) ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCompo) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCompo)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddBirdsMouth( 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 Point3d ptO( vdPar[0], vdPar[1], 0) ; // P01, P02 int nFlag = lround( vdPar[2]) ; // P05 double dAngle = Clamp( vdPar[3], 0.1, 179.) ; // P06 double dInclin1 = Clamp( vdPar[4], 0., 180.) ; // P07 double dInclin2 = Clamp( vdPar[5], 0., 180.) ; // P08 double dCutAng = Clamp( vdPar[6], 0., 179.) ; // P09 double dCutIncl = Clamp( vdPar[7], 0., 179.) ; // P10 double dDepth1 = Clamp( vdPar[8], 0., 50000.) ; // P11 double dDepth2 = Clamp( vdPar[9], 0., 50000.) ; // P12 double dWidth = Clamp( vdPar[10], 0., 50000.) ; // P13 if ( dWidth < EPS_SMALL) dWidth = GetSideWidth( nSide) - ptO.y ; double dHeightCnt = Clamp( vdPar[11], 0., 50000.) ; // P14 double dWidthCnt = Clamp( vdPar[12], 0., 50000.) ; // P15 // punti estremi dell'intersezione tra le facce principali Point3d ptP = ptO - Z_AX * dDepth1 ; Vector3d vtD = FromPolar( 1, dAngle) ; if ( nGroup == 4) vtD.Mirror( X_AX) ; double dDist = dWidth / abs( vtD.y) ; Point3d ptQ = ptO + vtD * dDist - Z_AX * dDepth2 ; // calcolo delle normali due facce principali Vector3d vtR = ptQ - ptP ; vtR.Normalize() ; Vector3d vtN1 = ( vtR ^ Z_AX) ^ vtR ; vtN1.Normalize() ; vtN1.Rotate( vtR, ( nGroup == 3 ? dInclin1 : - dInclin1)) ; Vector3d vtN2 = - ( vtR ^ Z_AX) ^ vtR ; vtN2.Rotate( vtR, ( nGroup == 3 ? dInclin2 : - dInclin2)) ; vtN2.Normalize() ; // creo il poligono della prima faccia Polygon3d plyFace1 ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyFace1)) return false ; // creo il poligono della seconda faccia Polygon3d plyFace2 ; if ( ! CreatePolygonInBox( ptP, vtN2, nSide, plyFace2)) return false ; // trimmo tra loro le due facce if ( ! TrimPolygons( plyFace1, plyFace2, false, false)) return false ; // eventuale terza faccia (offset della seconda) di contenimento della prima Polygon3d plyFace3 ; if ( dWidthCnt > EPS_SMALL && plyFace1.GetSideCount() > 0) { // la creo come offset della seconda Point3d ptT = ptP + vtN2 * dWidthCnt ; if ( ! CreatePolygonInBox( ptT, - vtN2, nSide, plyFace3)) return false ; // trimmo tra loro prima e terza if ( ! TrimPolygons( plyFace1, plyFace3, false, false)) return false ; } // eventuale quarta faccia (offset della prima) di contenimento della seconda Polygon3d plyFace4 ; if ( dHeightCnt > EPS_SMALL && plyFace2.GetSideCount() > 0) { // la creo come offset della prima Point3d ptT = ptP + vtN1 * dHeightCnt ; if ( ! CreatePolygonInBox( ptT, - vtN1, nSide, plyFace4)) return false ; // trimmo tra loro seconda e quarta if ( ! TrimPolygons( plyFace2, plyFace4, false, false)) return false ; } // eventuale quinta faccia (limite di fronte) Polygon3d plyFace5 ; if ( abs( ptO.y) > EPS_SMALL) { // imposto la normale per faccia anti-parallela al fronte Vector3d vtN5 = Y_AX ; // se caso generico if ( dCutAng > EPS_ANG_SMALL && dCutIncl > EPS_ANG_SMALL) { Vector3d vtRe = vtR ; vtRe.Rotate( vtN1, (( nGroup == 3) ? dCutAng : -dCutAng)) ; vtN5 = -vtN1 ; vtN5.Rotate( vtRe, (( nGroup == 3) ? -dCutIncl : dCutIncl)) ; } // calcolo la faccia if ( ! CreatePolygonInBox( ptP, vtN5, nSide, plyFace5)) return false ; // trimmo con le altre if ( ! TrimPolygons( plyFace5, plyFace1, false, false) || ! TrimPolygons( plyFace5, plyFace2, false, false) || ! TrimPolygons( plyFace5, plyFace3, false, false) || ! TrimPolygons( plyFace5, plyFace4, false, false)) return false ; } // eventuale sesta faccia (limite dietro) Polygon3d plyFace6 ; if ( abs( ptO.y + dWidth - GetSideWidth( nSide)) > EPS_SMALL) { // imposto la normale per faccia parallela al fronte Vector3d vtN6 = -Y_AX ; // se caso generico if ( dCutAng > EPS_ANG_SMALL && dCutIncl > EPS_ANG_SMALL) { // se esiste la faccia 5, è opposta if ( plyFace5.GetSideCount() > 0) vtN6 = - plyFace5.GetVersN() ; // altrimenti la calcolo else { Vector3d vtRe = - vtR ; vtRe.Rotate( vtN1, (( nGroup == 3) ? -dCutAng : dCutAng)) ; vtN6 = -vtN1 ; vtN6.Rotate( vtRe, (( nGroup == 3) ? dCutIncl : -dCutIncl)) ; } } // calcolo la faccia if ( ! CreatePolygonInBox( ptQ, vtN6, nSide, plyFace6)) return false ; // trimmo con le altre if ( ! TrimPolygons( plyFace6, plyFace1, false, false) || ! TrimPolygons( plyFace6, plyFace2, false, false) || ! TrimPolygons( plyFace6, plyFace3, false, false) || ! TrimPolygons( plyFace6, plyFace4, false, false)) return false ; } // creo la trimesh dalle facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyFace1) || ! DoSewing( pStm, plyFace2) || ! DoSewing( pStm, plyFace3) || ! DoSewing( pStm, plyFace4) || ! DoSewing( pStm, plyFace5) || ! DoSewing( pStm, plyFace6)) 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::AddRidgeLap( 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 dStartX = vdPar[0] ; // P01 int nFlag = lround( vdPar[1]) ; // P02 double dAngle = Clamp( vdPar[2], 0.1, 179.9) ; // P06 double dDepth = Clamp( vdPar[3], 1., 50000.) ; // P11 double dWidth = Clamp( vdPar[4], 1., 50000.) ; // P12 double dHoDiam = Clamp( vdPar[5], 0., 1000.) ; // P13 Point3d ptP( dStartX, (( nFlag == 0) ? 0 : GetSideWidth( nSide)), - dDepth) ; // calcolo la normale alla prima faccia del taglio Vector3d vtN = FromPolar( 1, 90 - dAngle) ; if ( nGroup == 2) vtN.Mirror( X_AX) ; if ( nFlag != 0) vtN.Mirror( Y_AX) ; // creo il primo poligono di taglio Polygon3d plyFace1 ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyFace1)) return false ; // creo il secondo poligono di taglio Polygon3d plyFace2 ; if ( ! CreatePolygonInBox( ptP, Z_AX, nSide, plyFace2)) return false ; // creo il terzo poligono di taglio Polygon3d plyFace3 ; if ( ! CreatePolygonInBox( ptP - vtN * dWidth, vtN, nSide, plyFace3)) return false ; // trim tra queste facce if ( ! TrimPolygons( plyFace1, plyFace2, true, false) || ! TrimPolygons( plyFace2, plyFace3, false, false)) return false ; // creo la trimesh dalle facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyFace1) || ! DoSewing( pStm, plyFace2) || ! DoSewing( pStm, plyFace3)) 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] ; // P01 double dStartY = vdPar[1] ; // P02 double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; // P03 int nFlag = lround( vdPar[3]) ; // P04 double dAngle = Clamp( vdPar[4], 0.1, 179.9) ; // P06 double dInclination = Clamp( vdPar[5], 0.1, 179.9) ; // P07 double dSlope = Clamp( vdPar[6], -89.9, 89.9) ; // P08 double dLeadAngle = Clamp( vdPar[7], 0., 179.9) ; // P09 double dLeadIncl = Clamp( vdPar[8], 0., 179.9) ; // P10 double dDepth = vdPar[9] ; // P11 double dLength = Clamp( vdPar[10], 1., 99999.) ; // P12 double dChAng = Clamp( vdPar[11], 0., 89.) ; // P13 double dWidth = ( ( vdPar[12] > EPS_SMALL) ? vdPar[12] : GetSideWidth( nSide) - dStartY) ; // P14 Point3d ptP( dStartX, dStartY, dStartZ) ; // disabilito nFlag nFlag = 0 ; // 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)) { // senza angolo di smusso su sola faccia inizio (condizioni da manuale BTL) if ( dStartZ < - EPS_SMALL || dLeadAngle > EPS_ANG_SMALL || dLeadIncl > EPS_ANG_SMALL || dChAng < EPS_ANG_SMALL || abs( dInclination - 90.) > EPS_ANG_SMALL || abs( dSlope) > EPS_ANG_SMALL) { if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyStart)) return false ; } // con angolo di smusso else { Vector3d vtNr = vtN1 ; if ( dChAng > EPS_ANG_SMALL) { Vector3d vtR = FromPolar( 1, dAngle) ; if ( nGroup == 4) vtR.Mirror( X_AX) ; vtNr.Rotate( vtR, (( nGroup == 3) ? dChAng : -dChAng)) ; } Point3d ptQ = ptP - Z_AX * dDepth ; if ( ! CreatePolygonInBox( ptQ, vtNr, 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 = - vtN1 ; if ( nGroup == 3) { vtN3.Mirror( X_AX) ; vtAx.Invert() ; } vtN3.Rotate( vtAx, dSlope) ; // facce davanti e dietro Vector3d vtN2 ; 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 ; } vtN2 = Y_AX ; } 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) ; vtN2 = vtN2f ; } // 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 ; Vector3d vtEdge = vtN1 ^ vtN2 ; vtEdge.Normalize() ; double dDist = dDepth / vtEdge.z ; if ( (nFlag & 16) == 0) { if ( ! CreatePolygonInBox( ptP - dDist * vtEdge, 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 int nFlag = lround( vdPar[2]) ; // P04 double dDepth = Clamp( vdPar[3], 0., 50000.) ; // P11 double dLength = Clamp( vdPar[4], 1., 99999.) ; // P12 double dWidth = Clamp( vdPar[5], 1., 50000.) ; // P13 Point3d ptP( vdPar[0], vdPar[1] - 0.5 * dWidth, 0.) ; // P01, P02 // 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 ( ! TrimPolygons( plyStart, plyFront, false, false)) return false ; if ( ! TrimPolygons( plyStart, plyBack, false, false)) return false ; if ( ! TrimPolygons( plyEnd, plyFront, false, false)) return false ; if ( ! TrimPolygons( plyEnd, plyBack, 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 ( ! TrimPolygons( plyBottom, plyStart, false, false)) return false ; if ( ! TrimPolygons( plyBottom, plyEnd, false, false)) return false ; if ( ! TrimPolygons( plyBottom, plyFront, false, false)) return false ; if ( ! TrimPolygons( plyBottom, 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::AddChamfer( 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 double dPos = vdPar[0] ; // P01 int nFlag = lround( vdPar[1]) ; // P04 double dDepth = Clamp( vdPar[2], 1., 100.) ; // P11 double dLen = Clamp( vdPar[3], 0., 100000.) ; // P12 int nExit = lround( vdPar[4]) ; // P15 // determino posizione di inizio e fine double dStart = ( nGroup == 4 ? dPos : dPos - dLen) ; double dEnd = ( nGroup == 4 ? dPos + dLen : dLen) ; if ( dLen < EPS_SMALL) { dStart = 0 ; dEnd = GetSideLength( nSide) ; } // creo gli smussi richiesti int nEnable[4] = { 1, 2, 4, 8} ; for ( int i = 1 ; i <= 4 ; ++ i) { // se smusso non richiesto, vado oltre if ( ( nFlag & nEnable[i-1]) == 0) continue ; // assegno il fianco di costruzione effettivo int nRefSide = i ; // calcolo il piano di fondo Vector3d vtN( 0, - SQRT1_2, SQRT1_2) ; Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ORIG - vtN * dDepth * SQRT1_2, vtN, nRefSide, plyBottom)) return false ; // calcolo il piano di inizio Vector3d vtNs = X_AX ; if ( nExit == 1) { vtNs.Rotate( Y_AX, -45) ; vtNs.Rotate( X_AX, 45) ; } Polygon3d plyStart ; if ( ! CreatePolygonInBox( Point3d(dStart, 0, 0), vtNs, nRefSide, plyStart)) return false ; // calcolo il piano di fine Vector3d vtNe = -X_AX ; if ( nExit == 1) { vtNe.Rotate( Y_AX, 45) ; vtNe.Rotate( X_AX, 45) ; } Polygon3d plyEnd ; if ( ! CreatePolygonInBox( Point3d(dEnd, 0, 0), vtNe, nRefSide, plyEnd)) return false ; // eseguo trim tra le facce if ( ! TrimPolygons( plyBottom, plyStart, false, false) || ! TrimPolygons( plyBottom, plyEnd, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyBottom) ; DoSewing( pStm, plyStart) ; DoSewing( pStm, plyEnd) ; 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 string sMyDes = ToString( i) + "-" + sDes ; SetNameAndInfo( nId, nGroup, nProc, nSide, sMyDes, nProcId) ; // parametri DBLVECTOR vdMyPar = vdPar ; vdMyPar[1] = nEnable[i] ; SetParams( nId, vnDPar, vdMyPar) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; } return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddPocket( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 10) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], - vdPar[7]) ; // P01, P02, P11 int nFlag = lround( vdPar[2]) ; // P04 double dAngle = Clamp( vdPar[3], -179.9, 179.9) ; // P06 double dIncl = Clamp( vdPar[4], -179.9, 179.9) ; // P07 double dSlope = Clamp( vdPar[5], -179.9, 179.9) ; // P08 double dIntAng = Clamp( vdPar[6], 0.1, 179.9) ; // P10 double dLen = Clamp( vdPar[8], 0., 50000.) ; // P12 double dWidth = Clamp( vdPar[9], 0., 50000.) ; // P13 // riferimento rototraslato Frame3d frRef( ptP) ; frRef.Rotate( ptP, frRef.VersZ(), dAngle) ; frRef.Rotate( ptP, frRef.VersY(), dIncl) ; frRef.Rotate( ptP, frRef.VersX(), dSlope) ; // creo il poligono della faccia di fondo Vector3d vtN1 = frRef.VersZ() ; Polygon3d plyFace1 ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyFace1)) return false ; // creo il poligono della faccia sinistra Vector3d vtN2 = frRef.VersX() ; vtN2.Rotate( frRef.VersZ(), dIntAng - 90) ; Polygon3d plyFace2 ; if ( ! CreatePolygonInBox( ptP, vtN2, nSide, plyFace2)) return false ; // creo il poligono della faccia destra Polygon3d plyFace4 ; if ( ! CreatePolygonInBox( ptP + vtN2 * dLen, - vtN2, nSide, plyFace4)) return false ; // creo il poligono della faccia davanti Vector3d vtN3 = frRef.VersY() ; Polygon3d plyFace3 ; if ( ! CreatePolygonInBox( ptP, vtN3, nSide, plyFace3)) return false ; // creo il poligono della faccia dietro Polygon3d plyFace5 ; if ( ! CreatePolygonInBox( ptP + vtN3 * dWidth, - vtN3, nSide, plyFace5)) return false ; // trimmo tra loro le facce if ( ! TrimPolygons( plyFace1, plyFace2, false, false) || ! TrimPolygons( plyFace1, plyFace3, false, false) || ! TrimPolygons( plyFace1, plyFace4, false, false) || ! TrimPolygons( plyFace1, plyFace5, false, false) || ! TrimPolygons( plyFace2, plyFace3, false, false) || ! TrimPolygons( plyFace3, plyFace4, false, false) || ! TrimPolygons( plyFace4, plyFace5, false, false) || ! TrimPolygons( plyFace5, plyFace2, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyFace1) ; DoSewing( pStm, plyFace2) ; DoSewing( pStm, plyFace3) ; DoSewing( pStm, plyFace4) ; DoSewing( pStm, plyFace5) ; 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]) ; // P01, P02, P03 double dAngHor = Clamp( vdPar[3], 0., 360.) ; // P06 double dAngVert = Clamp( abs( vdPar[4]), 1., 179.) ; // P07 double dDepth = vdPar[5] / sin( dAngVert * DEGTORAD) ; // P11 double dRad = vdPar[6] / 2 ; // P12 // 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à in globale Frame3d frRef = GetSideFrame( nSide) ; pArc->ToGlob( frRef) ; Vector3d vtNG = pArc->GetNormVersor() ; // determino i punti iniziale e finale Point3d ptStart = pArc->GetCenter() ; Point3d ptEnd = ptStart - vtNG * dDepth ; // verifico se inizio su faccia bool bStartClosed = true ; double dSinStart = 0 ; for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_LEFT ; ++ i) { Plane3d plSide = GetSidePlane( i) ; if ( PointInPlaneApprox( ptStart, plSide) && vtNG * plSide.vtN > COS_ALMOST_PERP) { bStartClosed = false ; dSinStart = sqrt( max( 0., 1 - vtNG * plSide.vtN)) ; break ; } } double dStartAgg = (( bStartClosed || dSinStart < EPS_SMALL) ? 0 : dRad * dSinStart + LEN_EXTRUS_AGG) ; // verifico se fine su faccia bool bEndClosed = true ; double dSinEnd = 0 ; for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_LEFT ; ++ i) { Plane3d plSide = GetSidePlane( i) ; if ( PointInPlaneApprox( ptEnd, plSide) && - vtNG * plSide.vtN > COS_ALMOST_PERP) { bEndClosed = false ; dSinEnd = sqrt( max( 0., 1 + vtNG * plSide.vtN)) ; break ; } } double dEndAgg = (( bEndClosed || dSinEnd < EPS_SMALL) ? 0 : dRad * dSinEnd + LEN_EXTRUS_AGG) ; // approssimo la circonferenza con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL ; if ( ! pArc->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( vtNG) ; // creo la superficie trimesh laterale del foro PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, - vtNG * ( dDepth + dStartAgg + dEndAgg))) return false ; pStm->Translate( vtNG * dStartAgg) ; // se chiuso, creo la superficie trimesh di fondo del foro if ( bEndClosed) { PtrOwner pStmBot( CreateSurfTriMesh()) ; if ( IsNull( pStmBot) || ! pStmBot->CreateByPointCurve( ptStart, PL)) return false ; pStmBot->Translate( - vtNG * dDepth) ; pStm->DoSewing( *pStmBot) ; } // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pArc)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; 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 = lround( 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]) < 100 * EPS_SMALL ? 100 * EPS_SMALL : vdPar[10]) ; double dTenM2 = ( abs( vdPar[11]) < 100 * EPS_SMALL ? 100 * 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->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 TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvTen) ; // 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) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // 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 = lround( 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) ; vtN2.Invert() ; } Vector3d vtN3 = vtN1 ^ vtN2 ; // 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 TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvMort) ; // 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) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nMId}) ; // 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 = lround( 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()) ; // definisco la superficie PtrOwner pStm ; // creo la regione del contorno esterno PtrOwner pExt( CreateCurveComposite()) ; if ( IsNull( pExt)) return false ; if ( pExt->FromPolyLine( plyCut.GetPolyLine())) { 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 pStm.Set( 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 ; if ( IsNull( pStm)) pStm.Set( Release( pStmTen)) ; else pStm->DoSewing( *pStmTen) ; // creo la superficie trimesh di fondo della mortasa PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL)) return false ; pStmCap->Translate( - frMort.VersZ() * dMortD) ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvTen) ; // 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) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDovetailTenon( 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 = lround( 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 dTenW = vdPar[6] ; double dTenA = Clamp( vdPar[7], 0., 30.) ; double dTenH = vdPar[8] ; double dFillet = vdPar[9] / 2 ; if ( dFillet < DTMILL_DEF_RAD && dTenW + 2 * dFillet >= 2 * DTMILL_DEF_RAD) { dTenW -= 2 * ( DTMILL_DEF_RAD - dFillet) ; dFillet = DTMILL_DEF_RAD ; } 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, dTenH) ; ptCen.ToGlob( frTen) ; // creo il contorno basso del tenone double dTenHW = 0.5 * dTenW ; PolyArc PB ; double dX0 = 0 ; double dY0 = - dTenM1 - dTenL ; PB.AddUPoint( 0, Point3d( dX0, dY0, 0), 0) ; double dX1 = dTenHW ; double dY1 = dY0 ; PB.AddUPoint( 1, Point3d( dX1, dY1, 0), 0) ; double dX2 = dX1 + dFillet * cos( dTenA * DEGTORAD) ; double dY2 = dY1 + dFillet * ( 1 - sin( dTenA * DEGTORAD)) ; double dBulge2 = tan( ( ANG_RIGHT - dTenA) / 4 * DEGTORAD) ; PB.ModifyLastBulge( dBulge2) ; PB.AddUPoint( 2, Point3d( dX2, dY2, 0), 0) ; double dX3 = dX2 + ( - dTenM1 - dY2) * sin( dTenA * DEGTORAD) ; double dY3 = - dTenM1 ; PB.AddUPoint( 3, Point3d( dX3, dY3, 0), 0) ; PolyArc PA = PB ; PA.Mirror( ORIG, X_AX) ; PA.Invert( true) ; PA.Join( PB, 3) ; PtrOwner pCrvTen( CreateCurveComposite()) ; if ( IsNull( pCrvTen) || ! pCrvTen->FromPolyArc( PA)) return false ; pCrvTen->SetExtrusion( Z_AX) ; pCrvTen->ToGlob( frTen) ; // lo approssimo con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL1 ; if ( ! pCrvTen->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL1) || ! pCompo->FromPolyLine( PL1)) return false ; pCompo->Close() ; pCompo->SetExtrusion( frTen.VersZ()) ; // Creo il contorno alto del tenone PtrOwner pOffs( pCrvTen->Clone()) ; if ( IsNull( pOffs)) return false ; double dOffs = dTenH * tan( DOVETAIL_DEF_ANG * DEGTORAD) ; pOffs->SimpleOffset( dOffs, ICurve::OFF_EXTEND) ; pOffs->Translate( frTen.VersZ() * dTenH) ; // lo allungo opportunamente ad entrambi gli estremi double dAll2 = dOffs * tan( dTenA * DEGTORAD) ; pOffs->ExtendStartByLen( dAll2) ; pOffs->ExtendEndByLen( dAll2) ; // lo approssimo con una spezzata PolyLine PL2 ; if ( ! pOffs->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL2)) return false ; // 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->CreateByTwoCurves( PL1, PL2)) return false ; pStm->DoSewing( *pStmTen) ; // Creo la superficie trimesh di chiusura del tenone Point3d ptTmp ; PolyLine PL3 ; PL1.GetFirstPoint( ptTmp) ; PL3.AddUPoint( 0, ptTmp) ; PL2.GetFirstPoint( ptTmp) ; PL3.AddUPoint( 1, ptTmp) ; PolyLine PL4 ; PL1.GetLastPoint( ptTmp) ; PL4.AddUPoint( 0, ptTmp) ; PL2.GetLastPoint( ptTmp) ; PL4.AddUPoint( 1, ptTmp) ; PtrOwner pStmTen2( CreateSurfTriMesh()) ; if ( IsNull( pStmTen2) || ! pStmTen2->CreateByTwoCurves( PL3, PL4)) return false ; pStm->DoSewing( *pStmTen2) ; // Creo la superficie trimesh di testa del tenone PL2.Close() ; PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL2)) return false ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvTen) ; // 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) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDovetailMortise( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 14) return false ; // sistemo i dati double dStartX = vdPar[0] ; double dStartY = vdPar[1] ; double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; Point3d ptP( dStartX, dStartY, dStartZ) ; int nFlag = lround( vdPar[3]) ; int nPock = lround( vdPar[4]) ; double dAngle = Clamp( vdPar[5], -180.0, 180.0) ; double dMortW = vdPar[7] ; double dMortA = Clamp( vdPar[8], 0., 30.) ; double dMortD = vdPar[9] ; double dFillet = vdPar[10] / 2 ; if ( dFillet < DTMILL_DEF_RAD && dMortW + 2 * dFillet >= 2 * DTMILL_DEF_RAD) { dMortW -= 2 * ( DTMILL_DEF_RAD - dFillet) ; dFillet = DTMILL_DEF_RAD ; } double dStrutAng = Clamp( vdPar[6], 0.1, 179.9) ; double dMortM1 = vdPar[12] ; double dMortM2 = vdPar[13] ; double dMortL = Clamp( vdPar[11] / sin( dStrutAng * DEGTORAD) - dMortM1 - dMortM2, 1., 99999.) ; // calcolo riferimento della faccia sopra Frame3d frMort ; frMort.Rotate( ORIG, Z_AX, ( nGroup == 4 ? 90 + dAngle : - 90 - dAngle)) ; frMort.ChangeOrig( ptP) ; frMort.ToGlob( GetSideFrame( nSide)) ; // calcolo il centro del fondo della mortasa Point3d ptCen( 0, - dMortM1 - 0.5 * dMortL, - dMortD) ; ptCen.ToGlob( frMort) ; // calcolo offset tra sotto e sopra double dOffs = dMortD * tan( DOVETAIL_DEF_ANG * DEGTORAD) ; // Creo il contorno alto della mortasa double dMortHW = 0.5 * dMortW ; PolyArc PB ; double dX0 = 0 ; double dY0 = - dMortM1 - dMortL ; PB.AddUPoint( 0, Point3d( dX0, dY0, 0), 0) ; double dX1 = dMortHW ; double dY1 = dY0 ; PB.AddUPoint( 1, Point3d( dX1, dY1, 0), 0) ; double dX2 = dX1 + dFillet * cos( dMortA * DEGTORAD) ; double dY2 = dY1 + dFillet * ( 1 - sin( dMortA * DEGTORAD)) ; double dBulge2 = tan( ( ANG_RIGHT - dMortA) / 4 * DEGTORAD) ; PB.ModifyLastBulge( dBulge2) ; PB.AddUPoint( 2, Point3d( dX2, dY2, 0), 0) ; double dX3 = dX2 + ( - dMortM1 - dY2) * sin( dMortA * DEGTORAD) ; double dY3 = - dMortM1 ; PB.AddUPoint( 3, Point3d( dX3, dY3, 0), 0) ; double dX4, dY4 ; if ( nPock == 0) { double dExtraLen = GetSideWidth( nSide) ; dX4 = dX3 + ( dExtraLen - dY3) * sin( dMortA * DEGTORAD) ; dY4 = dExtraLen ; } else { double dExtraLen = MAX_DTMORT_POCKET ; if ( dMortA > EPS_ANG_SMALL) dExtraLen = min( dOffs / sin( dMortA * DEGTORAD), MAX_DTMORT_POCKET) ; dX4 = dX3 ; dY4 = dExtraLen ; } PB.AddUPoint( 4, Point3d( dX4, dY4, 0), 0) ; PolyArc PA = PB ; PA.Mirror( ORIG, X_AX) ; PA.Invert( true) ; PA.Join( PB, 4) ; PtrOwner pCrvTop( CreateCurveComposite()) ; if ( IsNull( pCrvTop) || ! pCrvTop->FromPolyArc( PA)) return false ; pCrvTop->SetExtrusion( Z_AX) ; pCrvTop->ToGlob( frMort) ; // lo approssimo con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL2 ; if ( ! pCrvTop->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL2) || ! pCompo->FromPolyLine( PL2)) return false ; pCompo->Close() ; pCompo->SetExtrusion( frMort.VersZ()) ; // Creo il contorno basso della mortasa PtrOwner pCrvMort( pCrvTop->Clone()) ; if ( IsNull( pCrvMort)) return false ; pCrvMort->SimpleOffset( dOffs, ICurve::OFF_EXTEND) ; pCrvMort->Translate( - frMort.VersZ() * dMortD) ; // se senza tasca, lo allungo opportunamente ad entrambi gli estremi if ( nPock == 0) { double dAll2 = dOffs * tan( dMortA * DEGTORAD) ; pCrvMort->ExtendStartByLen( dAll2) ; pCrvMort->ExtendEndByLen( dAll2) ; } // lo approssimo con una spezzata PolyLine PL1 ; if ( ! pCrvMort->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL1)) return false ; // Creo la superficie trimesh laterale della mortasa PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByTwoCurves( PL2, PL1)) return false ; // aggiungo la superficie trimesh di chiusura della mortasa Point3d ptTmp ; PolyLine PL3 ; PL1.GetFirstPoint( ptTmp) ; PL3.AddUPoint( 0, ptTmp) ; PL2.GetFirstPoint( ptTmp) ; PL3.AddUPoint( 1, ptTmp) ; PolyLine PL4 ; PL1.GetLastPoint( ptTmp) ; PL4.AddUPoint( 0, ptTmp) ; PL2.GetLastPoint( ptTmp) ; PL4.AddUPoint( 1, ptTmp) ; PtrOwner pStmMrt( CreateSurfTriMesh()) ; if ( IsNull( pStmMrt) || ! pStmMrt->CreateByTwoCurves( PL3, PL4)) return false ; pStm->DoSewing( *pStmMrt) ; // aggiungo la superficie trimesh di fondo della mortasa PL1.Close() ; PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL1)) return false ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvMort) ; // 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) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nMId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDtMortiseFront( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 14) return false ; // sistemo i dati double dStartX = vdPar[0] ; double dStartY = vdPar[1] ; double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; Point3d ptP( dStartX, dStartY, dStartZ) ; int nFlag = lround( vdPar[3]) ; int nPock = lround( vdPar[4]) ; double dAngle = Clamp( vdPar[5], 0.1, 179.9) ; double dInclination = Clamp( vdPar[6], 0.1, 179.9) ; double dRot = Clamp( vdPar[7], 0.1, 179.9) ; double dMortW = vdPar[8] ; double dMortA = Clamp( vdPar[9], 0., 30.) ; double dMortD = vdPar[10] ; double dFillet = vdPar[11] / 2 ; if ( dFillet < DTMILL_DEF_RAD && dMortW + 2 * dFillet >= 2 * DTMILL_DEF_RAD) { dMortW -= 2 * ( DTMILL_DEF_RAD - dFillet) ; dFillet = DTMILL_DEF_RAD ; } double dMortM1 = ( abs( vdPar[12]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[12]) ; double dMortM2 = ( abs( vdPar[13]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[13]) ; // 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, -dMortD) ; ptCen.ToGlob( frMort) ; // calcolo offset tra sotto e sopra double dOffs = dMortD * tan( DOVETAIL_DEF_ANG * DEGTORAD) ; // Creo il contorno alto della mortasa double dMortHW = 0.5 * dMortW ; PolyArc PB ; double dX0 = 0 ; double dY0 = - dMortM1 - dMortL ; PB.AddUPoint( 0, Point3d( dX0, dY0, 0), 0) ; double dX1 = dMortHW ; double dY1 = dY0 ; PB.AddUPoint( 1, Point3d( dX1, dY1, 0), 0) ; double dX2 = dX1 + dFillet * cos( dMortA * DEGTORAD) ; double dY2 = dY1 + dFillet * ( 1 - sin( dMortA * DEGTORAD)) ; double dBulge2 = tan( ( ANG_RIGHT - dMortA) / 4 * DEGTORAD) ; PB.ModifyLastBulge( dBulge2) ; PB.AddUPoint( 2, Point3d( dX2, dY2, 0), 0) ; double dX3 = dX2 + ( - dMortM1 - dY2) * sin( dMortA * DEGTORAD) ; double dY3 = - dMortM1 ; PB.AddUPoint( 3, Point3d( dX3, dY3, 0), 0) ; double dX4, dY4 ; if ( nPock == 0) { double dExtraLen = GetSideWidth( nSide) ; dX4 = dX3 + ( dExtraLen - dY3) * sin( dMortA * DEGTORAD) ; dY4 = dExtraLen ; } else { double dExtraLen = MAX_DTMORT_POCKET ; if ( dMortA > EPS_ANG_SMALL) dExtraLen = min( dOffs / sin( dMortA * DEGTORAD), MAX_DTMORT_POCKET) ; dX4 = dX3 ; dY4 = dExtraLen ; } PB.AddUPoint( 4, Point3d( dX4, dY4, 0), 0) ; PolyArc PA = PB ; PA.Mirror( ORIG, X_AX) ; PA.Invert( true) ; PA.Join( PB, 4) ; PtrOwner pCrvTop( CreateCurveComposite()) ; if ( IsNull( pCrvTop) || ! pCrvTop->FromPolyArc( PA)) return false ; pCrvTop->SetExtrusion( Z_AX) ; pCrvTop->ToGlob( frMort) ; // lo approssimo con una spezzata PtrOwner pCompo( CreateCurveComposite()) ; PolyLine PL2 ; if ( ! pCrvTop->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL2) || ! pCompo->FromPolyLine( PL2)) return false ; pCompo->Close() ; 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 della mortasa SurfFlatRegionByContours SfrMort ; SfrMort.AddCurve( pCompo->Clone()) ; PtrOwner pMort( SfrMort.GetSurf()) ; if ( IsNull( pMort)) return false ; // sottraggo la regione della mortasa da quella esterna if ( ! pReg->Subtract( *pMort)) return false ; // ne deduco la superficie trimesh PtrOwner pStm( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStm)) return false ; // Creo il contorno basso della mortasa PtrOwner pCrvMort( pCrvTop->Clone()) ; if ( IsNull( pCrvMort)) return false ; pCrvMort->SimpleOffset( dOffs, ICurve::OFF_EXTEND) ; pCrvMort->Translate( - frMort.VersZ() * dMortD) ; // se senza tasca, lo allungo opportunamente ad entrambi gli estremi if ( nPock == 0) { double dAll2 = dOffs * tan( dMortA * DEGTORAD) ; pCrvMort->ExtendStartByLen( dAll2) ; pCrvMort->ExtendEndByLen( dAll2) ; } // lo approssimo con una spezzata PolyLine PL1 ; if ( ! pCrvMort->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL1)) return false ; // creo la superficie trimesh della mortasa PtrOwner pStmTen( CreateSurfTriMesh()) ; if ( IsNull( pStmTen) || ! pStmTen->CreateByTwoCurves( PL2, PL1)) return false ; pStm->DoSewing( *pStmTen) ; // aggiungo la superficie trimesh di chiusura della mortasa Point3d ptTmp ; PolyLine PL3 ; PL1.GetFirstPoint( ptTmp) ; PL3.AddUPoint( 0, ptTmp) ; PL2.GetFirstPoint( ptTmp) ; PL3.AddUPoint( 1, ptTmp) ; PolyLine PL4 ; PL1.GetLastPoint( ptTmp) ; PL4.AddUPoint( 0, ptTmp) ; PL2.GetLastPoint( ptTmp) ; PL4.AddUPoint( 1, ptTmp) ; PtrOwner pStmMrt( CreateSurfTriMesh()) ; if ( IsNull( pStmMrt) || ! pStmMrt->CreateByTwoCurves( PL3, PL4)) return false ; pStm->DoSewing( *pStmMrt) ; // creo la superficie trimesh di fondo della mortasa PL1.Close() ; PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL1)) return false ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvMort) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvMort)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddMarking( 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) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; int nFlag = lround( vdPar[2]) ; double dAng = Clamp( vdPar[3], 1., 180.) ; double dIntAng = Clamp( vdPar[4], 0., 179.) ; double dWidth = Clamp( vdPar[5], 0., 50000.) ; double dQuadH = Clamp( vdPar[6], 0., 50000.) ; if ( abs( dQuadH) < EPS_SMALL) dQuadH = GetSideWidth( nSide) - ptP.y ; double dTextH = Clamp( vdPar[7], 0., 50000.) ; Vector3d vtD = FromPolar( 1, dAng) ; if ( nGroup == 4) vtD.Mirror( X_AX) ; // riferimento della faccia Frame3d frRef = GetSideFrame( nSide) ; int nMainId = GDB_ID_NULL ; INTVECTOR vAuxId ; // gestione marcatura if ( (nFlag & 1) == 0) { // una sola linea orizzontale if ( abs( dAng - 180.) < EPS_ANG_SMALL) { // creo la linea PtrOwner pLine( CreateCurveLine()) ; if ( IsNull( pLine)) return false ; // assegno i dati if ( ! pLine->SetPVL( ptP, vtD, dQuadH)) return false ; // imposto estrusione pLine->SetExtrusion( Z_AX) ; // porto la linea nel piano della faccia pLine->ToGlob( frRef) ; // eseguo trim della curva con le facce della trave if ( TrimFlatCurveWithBox( pLine)) { // inserisco la linea nel DB geometrico nMainId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pLine)) ; if ( nMainId == GDB_ID_NULL) return false ; } } // una o due linee inclinate e parallele else if ( abs( dWidth) < EPS_SMALL || abs( dIntAng) < EPS_ANG_SMALL) { // dati double dLen = dQuadH / vtD.y ; Point3d ptQ = ptP + X_AX * (( nGroup == 3) ? - dWidth : dWidth) ; // creo la prima linea PtrOwner pLine( CreateCurveLine()) ; if ( IsNull( pLine)) return false ; // assegno i dati if ( ! pLine->SetPVL( ptP, vtD, dLen)) return false ; // imposto estrusione pLine->SetExtrusion( Z_AX) ; // porto la linea nel piano della faccia pLine->ToGlob( frRef) ; // eseguo trim della curva con le facce della trave if ( TrimFlatCurveWithBox( pLine)) { // inserisco la linea nel DB geometrico nMainId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pLine)) ; if ( nMainId == GDB_ID_NULL) return false ; } // se richiesto, creo la seconda linea if ( abs( dWidth) > EPS_SMALL) { PtrOwner pLine2( CreateCurveLine()) ; if ( IsNull( pLine2)) return false ; // assegno i dati if ( ! pLine2->SetPVL( ptQ, vtD, dLen)) return false ; // imposto estrusione pLine2->SetExtrusion( Z_AX) ; // porto la linea nel piano della faccia pLine2->ToGlob( frRef) ; // eseguo trim della curva con le facce della trave if ( TrimFlatCurveWithBox( pLine2)) { // inserisco la linea nel DB geometrico int nId2 = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pLine2)) ; if ( nId2 == GDB_ID_NULL) return false ; if ( nMainId == GDB_ID_NULL) nMainId = nId2 ; else vAuxId.emplace_back( nId2) ; } } } // quadrangolo else { // dati double dLen = dQuadH / vtD.y ; Vector3d vtE = vtD ; vtE.Rotate( Z_AX, (( nGroup == 3) ? dIntAng : - dIntAng)) ; double dLen2 = GetSideWidth( nSide) ; if ( abs( vtE.x) > EPS_SMALL) dLen2 = dWidth / abs( vtE.x) ; // creo la prima linea PtrOwner pLine( CreateCurveLine()) ; if ( IsNull( pLine)) return false ; // assegno i dati if ( ! pLine->SetPVL( ptP, vtD, dLen)) return false ; // la inserisco nella composita PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pLine))) return false ; // aggiungo le successive linee pCompo->AddLine( ptP + vtD * dLen + vtE * dLen2) ; pCompo->AddLine( ptP + vtE * dLen2) ; pCompo->Close() ; // imposto estrusione pCompo->SetExtrusion( Z_AX) ; // porto la curva nel piano della faccia pCompo->ToGlob( frRef) ; // eseguo trim della curva con le facce della trave if ( TrimFlatCurveWithBox( pCompo)) { // inserisco la linea nel DB geometrico nMainId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCompo)) ; if ( nMainId == GDB_ID_NULL) return false ; } } } // gestione testo // !!! DA FARE !!! // assegno i dati principali if ( nMainId != GDB_ID_NULL) { // nome e info con tipo SetNameAndInfo( nMainId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nMainId, vnDPar, vdPar) ; string sKey = IKEY_PAR + ToString( nSPar, 2) ; m_pGDB->SetInfo( nMainId, sKey, sPar) ; // identificativi di geometrie ausiliarie SetAuxId( nMainId, vAuxId) ; // colore per linee di marcatura e testi m_pGDB->SetMaterial( nMainId, m_MarkCol) ; for each (auto nId in vAuxId) m_pGDB->SetMaterial( nId, m_MarkCol) ; } // altrimenti emetto segnalazione else { string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_INFO( GetEExLogger(), sOut.c_str()) } 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::AddSimpleScarf( 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 dStartX = vdPar[0] ; // P01 double dDepthRef = Clamp( vdPar[1], 0., 50000.) ; // P11 double dDepthOpp = Clamp( vdPar[2], 0., 50000.) ; // P12 double dLength = Clamp( vdPar[3], 0., 50000.) ; // P13 double dHoDiam1 = Clamp( vdPar[4], 0., 1000.) ; // P14 double dHoDiam2 = Clamp( vdPar[5], 0., 1000.) ; // P15 // calcolo la normale principale Vector3d vtN = ( nGroup == 2 ? - X_AX : X_AX) ; // punti di riferimento Point3d ptP1( dStartX, 0, - dDepthRef) ; Point3d ptP2( dStartX - vtN.x * dLength, 0, - GetSideHeight( nSide) + dDepthRef) ; // creo il primo poligono di taglio Polygon3d plyFace1 ; if ( ! CreatePolygonInBox( ptP1, vtN, nSide, plyFace1)) return false ; // creo il secondo poligono di taglio Vector3d vtM = ptP2 - ptP1 ; vtM.Normalize() ; vtM.Rotate( Y_AX, ( nGroup == 2 ? ANG_RIGHT : - ANG_RIGHT)) ; Polygon3d plyFace2 ; if ( ! CreatePolygonInBox( ptP1, vtM, nSide, plyFace2)) return false ; // creo il terzo poligono di taglio Polygon3d plyFace3 ; if ( ! CreatePolygonInBox( ptP2, vtN, nSide, plyFace3)) return false ; // trim tra queste facce if ( ! TrimPolygons( plyFace1, plyFace2, true, false) || ! TrimPolygons( plyFace2, plyFace3, false, false)) return false ; // creo la trimesh dalle facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyFace1) || ! DoSewing( pStm, plyFace2) || ! DoSewing( pStm, plyFace3)) 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::AddScarfJoint( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar) { // verifica dei parametri if ( vdPar.size() < 9) return false ; // sistemo i dati double dStartX = vdPar[0] ; // P01 double dInclination = Clamp( vdPar[1], 0., 90.) ; // P07 int nType = lround( vdPar[2]) ; // P09 double dLapLength = Clamp( vdPar[3], 0., 50000.) ; // P10 double dLapDepth = Clamp( vdPar[4], 0., 50000.) ; // P11 double dDepthOpp = Clamp( vdPar[5], 0., 50000.) ; // P12 double dLength = Clamp( vdPar[6], 0., 50000.) ; // P13 double dHoDiam1 = Clamp( vdPar[7], 0., 1000.) ; // P14 double dHoDiam2 = Clamp( vdPar[8], 0., 1000.) ; // P15 double dHeight = GetSideHeight( nSide) ; // aggiustamenti if ( nType == 0) { // devo calcolare dInclination, dLapLength e dDepthOpp (vedi note in Wiki) DBLVECTOR vdPoly( 3) ; vdPoly[0] = - dLapDepth * dLapDepth * ( dLength * dLength + dHeight * dHeight) ; vdPoly[1] = 2 * dHeight * dLapDepth * dLapDepth ; vdPoly[2] = dLength * dLength - dLapDepth * dLapDepth ; DBLVECTOR vdRoot ; int nRoots = PolynomialRoots( 2, vdPoly, vdRoot) ; if ( nRoots > 0 && vdRoot[0] > EPS_SMALL && vdRoot[0] < dHeight) dDepthOpp = vdRoot[0] ; else if ( nRoots > 1 && vdRoot[1] > EPS_SMALL && vdRoot[1] < dHeight) dDepthOpp = vdRoot[1] ; else return false ; dInclination = acos( dLapDepth / dDepthOpp) * RADTODEG ; dLapLength = ( sqrt( dLength * dLength + ( dHeight - dDepthOpp) * ( dHeight - dDepthOpp)) - dDepthOpp * sin( dInclination * DEGTORAD)) / 2 ; } // calcolo la direzione principale e quella ortogonale Vector3d vtV1 = - X_AX ; vtV1.Rotate( Y_AX, dInclination) ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Y_AX, ANG_RIGHT) ; // punti di riferimento Point3d ptP( dStartX + dLength, 0, -dHeight) ; Point3d ptQ = ptP + Z_AX * dDepthOpp ; Point3d ptR = ptQ + vtV1 * dLapLength ; Point3d ptS = ptR - vtV2 * dLapDepth ; Point3d ptT = ptP + vtV1 * dLength / abs( vtV1.x) ; Point3d ptU( dStartX, 0, 0) ; if ( nType == -1) { ptP = ptQ - vtV2 * dDepthOpp / vtV2.z ; ptU = ptT + vtV2 * ( - ptT.z) / vtV2.z ; } // creo il profilo PolyLine PL ; PL.AddUPoint( 0, ptP) ; PL.AddUPoint( 1, ptQ) ; PL.AddUPoint( 2, ptR) ; PL.AddUPoint( 3, ptS) ; PL.AddUPoint( 4, ptT) ; PL.AddUPoint( 5, ptU) ; if ( nGroup == 1) PL.Mirror( ptT, X_AX) ; // lo porto in globale Frame3d frSide = GetSideFrame( nSide) ; PL.ToGlob( frSide) ; // definisco la superficie PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, frSide.VersY() * GetSideWidth( nSide))) return false ; if ( nGroup == 1) pStm->Invert() ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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::AddStepJoint( 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 double dStartX = vdPar[0] ; // P01 int nType = lround( vdPar[1]) ; // P04 double dInclination = Clamp( vdPar[2], 0.1, 179.9) ; // P07 double dStepDepth = Clamp( vdPar[3], 0., 1000.) ; // P11 double dHeelDepth = Clamp( vdPar[4], 0., 1000.) ; // P12 double dTenHeight = Clamp( vdPar[5], 0., 1000.) ; // P14 double dTenWidth = Clamp( vdPar[6], 0., 1000.) ; // P15 // gestione angolo ottuso bool bMirrZ = ( dInclination > ANG_RIGHT) ; if ( bMirrZ) { dInclination = ANG_STRAIGHT - dInclination ; dStartX += ( nGroup == 2 ? -1 : 1) * GetSideHeight( nSide) / tan( dInclination * DEGTORAD) ; } // controllo del tipo if ( dStepDepth > EPS_SMALL && dHeelDepth > EPS_SMALL) nType = 0 ; else if ( dHeelDepth <= EPS_SMALL || abs( dInclination - ANG_RIGHT) < EPS_ANG_SMALL || dHeelDepth / cos( dInclination * DEGTORAD) > GetSideHeight( nSide) - EPS_SMALL) nType = 1 ; // definizione punti notevoli Point3d ptP( dStartX, 0, 0) ; Vector3d vtV1 = - X_AX ; vtV1.Rotate( Y_AX, dInclination) ; Point3d ptQ = ptP - vtV1 * GetSideHeight( nSide) / vtV1.z ; if ( dHeelDepth > EPS_SMALL) ptQ += - X_AX * dHeelDepth / sin( dInclination * DEGTORAD) ; Point3d ptS = ptQ ; if ( nType == 0) ptS += Z_AX * dHeelDepth / cos( dInclination * DEGTORAD) ; Point3d ptT = ptP ; if ( dStepDepth > EPS_SMALL) { double dAngT = ( ANG_STRAIGHT - dInclination) / 2 ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Y_AX, dAngT) ; ptT += - vtV2 * dStepDepth / sin( dAngT * DEGTORAD) ; } // creazione profilo PolyLine PL ; PL.AddUPoint( 0, ptP) ; PL.AddUPoint( 0, ptT) ; PL.AddUPoint( 0, ptS) ; PL.AddUPoint( 0, ptQ) ; if ( bMirrZ) { PL.Mirror( Point3d( 0, 0, - GetSideHeight( nSide) / 2), Z_AX) ; PL.Invert() ; } if ( nGroup == 1) PL.Mirror( ptP, X_AX) ; // lo porto in globale Frame3d frSide = GetSideFrame( nSide) ; PL.ToGlob( frSide) ; // definisco la superficie PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, frSide.VersY() * GetSideWidth( nSide))) return false ; if ( nGroup == 2) pStm->Invert() ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // 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::AddStepJointNotch( 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 double dStartX = vdPar[0] ; // P01 double dStartY = vdPar[1] ; // P02 int nType = lround( vdPar[2]) ; // P04 double dInclination = Clamp( vdPar[3], 0.1, 179.9) ; // P07 double dWidth = Clamp( vdPar[4], 0., 50000.) ; // P10 double dStepDepth = Clamp( vdPar[5], 0., 1000.) ; // P11 double dHeelDepth = Clamp( vdPar[6], 0., 1000.) ; // P12 double dStructHeight = Clamp( vdPar[7], 0., 50000.) ; // P13 double dTenHeight = Clamp( vdPar[8], 0., 1000.) ; // P14 double dTenWidth = Clamp( vdPar[9], 0., 1000.) ; // P15 // gestione angolo ottuso double dLen = dStructHeight / sin( dInclination * DEGTORAD) ; bool bMirrX = ( dInclination > ANG_RIGHT) ; if ( bMirrX) { dInclination = ANG_STRAIGHT - dInclination ; dStartX += ( nGroup == 4 ? dLen : - dLen) ; } // controllo del tipo if ( dStepDepth > EPS_SMALL && dHeelDepth > EPS_SMALL) nType = 0 ; else if ( dHeelDepth <= EPS_SMALL || abs( dInclination - ANG_RIGHT) < EPS_ANG_SMALL || dHeelDepth / cos( dInclination * DEGTORAD) > dLen - EPS_SMALL) nType = 1 ; // riferimento della faccia Frame3d frSide = GetSideFrame( nSide) ; // definizione punti notevoli Vector3d vtV1 = X_AX ; vtV1.Rotate( Y_AX, - dInclination) ; Point3d ptP( dStartX, dStartY, 0) ; Point3d ptQ = ptP + X_AX * dLen ; Point3d ptR = ptQ ; if ( dHeelDepth > EPS_SMALL) ptR += - vtV1 * dHeelDepth / sin( dInclination * DEGTORAD) ; Point3d ptS ; if ( nType == 0) ptS = ptQ - X_AX * dHeelDepth / ( sin( dInclination * DEGTORAD) * cos( dInclination * DEGTORAD)) ; else ptS = ptR ; Point3d ptT = ptP ; if ( dStepDepth > EPS_SMALL) { double dAngT = ( ANG_STRAIGHT - dInclination) / 2 ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Y_AX, - dAngT) ; ptT += - vtV2 * dStepDepth / sin( dAngT * DEGTORAD) ; } // creazione profilo double dU = 0 ; PolyLine PL ; if ( ! AreSamePointApprox( ptP, ptT)) { PL.AddUPoint( dU, ptP) ; PL.AddUPoint( ++dU, ptT) ; // se doppio lobo laterale, abbasso il centro per non avere problemi if ( ! AreSamePointApprox( ptS, ptR)) ptS -= Z_AX * 10 * EPS_SMALL ; } else if ( AreSamePointApprox( ptS, ptR)) PL.AddUPoint( dU, ptP) ; PL.AddUPoint( ++dU, ptS) ; PL.AddUPoint( ++dU, ptR) ; PL.AddUPoint( ++dU, ptQ) ; if ( bMirrX) { PL.Mirror( ptP, X_AX) ; PL.Invert() ; } if ( nGroup == 3) PL.Mirror( ptP, X_AX) ; // lo porto in globale PL.ToGlob( frSide) ; // definisco la superficie PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, frSide.VersY() * dWidth)) return false ; if ( nGroup == 3) pStm->Invert() ; // definisco ed aggiungo eventuale faccia anteriore if ( dStartY > EPS_SMALL) { // profilo superiore PolyLine PL2 = PL ; PL2.Scale( frSide, 1, 1, 0) ; // creo la superficie rigata PtrOwner pSfr( CreateSurfTriMesh()) ; if ( IsNull( pSfr) || ! pSfr->CreateByTwoCurves( PL, PL2)) return false ; // la unisco alla superficie principale if ( ! pStm->DoSewing( *pSfr)) return false ; } // definisco ed aggiungo eventuale faccia posteriore if ( dStartY + dWidth < GetSideWidth( nSide) - EPS_SMALL) { // profilo superiore PolyLine PL2 = PL ; PL2.Scale( frSide, 1, 1, 0) ; // creo la superficie rigata PtrOwner pSfr( CreateSurfTriMesh()) ; if ( IsNull( pSfr) || ! pSfr->CreateByTwoCurves( PL, PL2)) return false ; // la inverto e la traslo pSfr->Invert() ; pSfr->Translate( frSide.VersY() * dWidth) ; // la unisco alla superficie principale if ( ! pStm->DoSewing( *pSfr)) return false ; } // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // 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::AddProfileHeadCoCo( 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 dP01 = vdPar[0] ; double dP11 = Clamp( vdPar[1], 0., 1000.) ; double dP12 = Clamp( vdPar[2], -1000., 1000.) ; double dP13 = Clamp( vdPar[3], 0., 1000.) ; double dP14 = Clamp( vdPar[4], -1000., 1000.) ; double dP15 = Clamp( vdPar[5], 0., 1000.) ; Point3d ptP1( dP01, dP14 + dP11 + dP12, 0) ; Point3d ptP2( dP01 + dP13, dP14 + dP11 + dP12, 0) ; Point3d ptP3( dP01 + dP13, dP14 + dP11, 0) ; Point3d ptP4( dP01 + dP13 + dP11, dP14, 0) ; Point3d ptP5( dP01 + dP13 + dP11 + dP15, dP14, 0) ; Point3d ptP6( dP01 + dP13 + dP11 + dP15, 0, 0) ; // costruisco la curva del profilo PolyArc PA ; const double BULGE_90D = tan( 90.0 / 4 * DEGTORAD) ; PA.AddUPoint( 0, ptP1, 0) ; PA.AddUPoint( 0, ptP2, 0) ; PA.AddUPoint( 0, ptP3, 0) ; PA.ModifyLastBulge( (( nProc == 101) ? -BULGE_90D : BULGE_90D)) ; PA.AddUPoint( 0, ptP4, 0) ; PA.AddUPoint( 0, ptP5, 0) ; PA.AddUPoint( 0, ptP6, 0) ; PtrOwner pCrvCo( CreateCurveComposite()) ; if ( IsNull( pCrvCo) || ! pCrvCo->FromPolyArc( PA)) return false ; pCrvCo->SetExtrusion( Z_AX) ; pCrvCo->SetThickness( - GetSideWidth( nSide)) ; // se gruppo 3, simmetrico rispetto a X if ( nGroup == 3) pCrvCo->Mirror( ptP1, X_AX) ; // sistemo per riferimento faccia Frame3d frRef ; int nRefSide = ( ( nSide - 1) >= BTL_SIDE_FRONT ? ( nSide - 1) : BTL_SIDE_TOP) ; frRef = GetSideFrame( nRefSide) ; pCrvCo->ToGlob( frRef) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) ; PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, - frRef.VersZ() * GetSideWidth( nSide))) return false ; if ( nGroup == 4) pStm->Invert() ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // esterno deve sempre essere a destra della curva if ( nGroup == 3) { pCrvCo->Translate( - frRef.VersZ() * GetSideWidth( nSide)) ; pCrvCo->SetExtrusion( - frRef.VersZ()) ; } // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvCo) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCo)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProfileHeadCambered( 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 ptS( vdPar[0], vdPar[2], 0) ; Point3d ptE( vdPar[0] + vdPar[1], vdPar[5], 0) ; double dMax = vdPar[3] ; double dMin = vdPar[4] ; int nFlag = lround( vdPar[6]) ; // calcolo i punti di controllo const double COEFF_PCMAX = 1. / 3. ; const double COEFF_PCMIN = 2. / 3. ; const double PCTRL_COEFF = 1.5 ; double dRef1 = vdPar[2] * ( 1 - COEFF_PCMAX) + vdPar[5] * COEFF_PCMAX ; double dRef2 = vdPar[2] * ( 1 - COEFF_PCMIN) + vdPar[5] * COEFF_PCMIN ; Point3d ptCmax( vdPar[0] + vdPar[1] * COEFF_PCMAX, dRef1 + PCTRL_COEFF * ( dMax - dRef1), 0) ; Point3d ptCmin( vdPar[0] + vdPar[1] * COEFF_PCMIN, dRef2 + PCTRL_COEFF * ( dMin - dRef2), 0) ; // costruisco la curva del profilo PtrOwner pCrv( CreateCurveBezier()) ; if ( IsNull( pCrv)) return false ; pCrv->Init( 3, false) ; pCrv->SetControlPoint( 0, ptS) ; pCrv->SetControlPoint( 1, ptCmax) ; pCrv->SetControlPoint( 2, ptCmin) ; pCrv->SetControlPoint( 3, ptE) ; // verifico minimo/massimo const double MAX_ERR = 0.5 ; for ( int i = 1 ; i <= 10 ; ++ i) { BBox3d b3Crv ; pCrv->GetLocalBBox( b3Crv, BBF_EXACT) ; double dDeltaMax = dMax - b3Crv.GetMax().y ; double dDeltaMin = dMin - b3Crv.GetMin().y ; //string sOut = "I=" + ToString( i) + " Dmax=" + ToString( dDeltaMax,2) + " Dmin=" + ToString( dDeltaMin, 2) ; //LOG_INFO( GetEExLogger(), sOut.c_str()) if ( abs( dDeltaMax) > MAX_ERR || abs( dDeltaMin) > MAX_ERR) { ptCmax += Vector3d( 0, PCTRL_COEFF * dDeltaMax, 0) ; pCrv->SetControlPoint( 1, ptCmax) ; ptCmin += Vector3d( 0, PCTRL_COEFF * dDeltaMin, 0) ; pCrv->SetControlPoint( 2, ptCmin) ; } else break ; } // la approssimo con archi e rette PtrOwner pCrvCo( CreateCurveComposite()) ; if ( IsNull( pCrvCo) || ! pCrvCo->AddCurve( Release( pCrv))) return false ; pCrvCo->SetExtrusion( Z_AX) ; pCrvCo->SetThickness( - GetSideWidth( nSide)) ; pCrvCo->ArcsBezierCurvesToArcsPerpExtr( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG) ; // aggiungo la linea finale Point3d ptEnd ; pCrvCo->GetEndPoint( ptEnd) ; Vector3d vtEnd ; pCrvCo->GetEndDir( vtEnd) ; vtEnd.Rotate( Z_AX, -90) ; double dLen = ptEnd.y / abs( vtEnd.y) ; pCrvCo->AddLine( ptEnd + vtEnd * dLen) ; // se gruppo 3, simmetrico rispetto a X if ( nGroup == 3) pCrvCo->Mirror( ptS, X_AX) ; // sistemo per riferimento faccia Frame3d frRef ; int nRefSide = ( ( nSide - 1) >= BTL_SIDE_FRONT ? ( nSide - 1) : BTL_SIDE_TOP) ; frRef = GetSideFrame( nRefSide) ; pCrvCo->ToGlob( frRef) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) ; PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, - frRef.VersZ() * GetSideWidth( nSide))) return false ; if ( nGroup == 4) pStm->Invert() ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // esterno deve sempre essere a destra della curva if ( nGroup == 3) { pCrvCo->Translate( - frRef.VersZ() * GetSideWidth( nSide)) ; pCrvCo->SetExtrusion( - frRef.VersZ()) ; } // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvCo) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCo)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddRoundArch( 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 double dStartX = vdPar[0] ; // P01 double dCamber = Clamp( vdPar[1], -1000., 1000.) ; // P11 double dLength = Clamp( vdPar[2], 0., 30000.) ; // P12 // costruisco la curva del profilo bool bConvex = ( dCamber < 0) ; Point3d ptP1( dStartX - dLength / 2, ( bConvex ? - dCamber : 0), 0) ; Point3d ptP2( dStartX, ( bConvex ? 10 * EPS_SMALL : dCamber), 0) ; Point3d ptP3 = ptP1 + Vector3d( dLength, 0, 0) ; PtrOwner pCrv ; if ( ! pCrv.Set( GetArc3P( ptP1, ptP2, ptP3, false))) return nullptr ; PtrOwner pCrvCo( CreateCurveComposite()) ; if ( IsNull( pCrvCo) || ! pCrvCo->AddCurve( Release( pCrv))) return false ; pCrvCo->SetExtrusion( Z_AX) ; pCrvCo->SetThickness( - GetSideWidth( nSide)) ; // se convesso, aggiungo linea iniziale e finale if ( bConvex) { Point3d ptStart ; pCrvCo->GetStartPoint( ptStart) ; Vector3d vtStart ; pCrvCo->GetStartDir( vtStart) ; vtStart.Rotate( Z_AX, -90) ; double dLs = ptStart.y / abs( vtStart.y) ; pCrvCo->AddLine( ptStart + vtStart * dLs, false) ; Point3d ptEnd ; pCrvCo->GetEndPoint( ptEnd) ; Vector3d vtEnd ; pCrvCo->GetEndDir( vtEnd) ; vtEnd.Rotate( Z_AX, -90) ; double dLe = ptEnd.y / abs( vtEnd.y) ; pCrvCo->AddLine( ptEnd + vtEnd * dLe) ; } // sistemo per riferimento faccia Frame3d frRef ; int nRefSide = ( ( nSide - 1) >= BTL_SIDE_FRONT ? ( nSide - 1) : BTL_SIDE_TOP) ; frRef = GetSideFrame( nRefSide) ; pCrvCo->ToGlob( frRef) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL) ; PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, - frRef.VersZ() * GetSideWidth( nSide))) return false ; pStm->Invert() ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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( pCrvCo)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline if ( UseProcessToTrimOutline( nId)) TrimOutline( nId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddFreeContour( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, int nSPar, const DBLVECTOR& vdPar, const string& sPar) { // verifica dei parametri if ( vdPar.size() < 11) return false ; // sistemo i dati int nType = lround( vdPar[6]) ; // P08 Point3d ptP( vdPar[0], vdPar[1], vdPar[2]) ; // P01, P02, P03 Point3d ptM ; if ( nType == FreeContourEnt::ARC) ptM.Set( vdPar[8], vdPar[9], vdPar[10]) ; // P10, P11, P12 double dDepth = vdPar[3] ; // P05 double dAng = vdPar[4] ; // P06 int nNextId = lround( vdPar[7]) ; // P09 int nPocket = lround( vdPar[5]) ; // P07 // se inizio del contorno... if ( nType == FreeContourEnt::START || nType == FreeContourEnt::START_CNT0) { // verifico che la coda sia vuota if ( m_FcData.size() > 0) { string sOut = " Error : found previous data in Free Contour (PId=" + ToString( nProcId) + ")" ; LOG_ERROR( GetEExLogger(), sOut.c_str()) } // in ogni caso la svuoto m_FcData.clear() ; // imposto riferimento m_FcRef = frRef ; // verifico spessore if ( dDepth < EPS_SMALL) dDepth = GetSideHeight( nSide) ; // salvo spessore m_dFcDepth = dDepth ; // salvo flag di svuotatura m_bFcPocket = ( nPocket == 1) ; } // aggiusto i punti per il riferimento ptP.ToGlob( m_FcRef) ; ptM.ToGlob( m_FcRef) ; // aggiungo i dati alla coda m_FcData.emplace_back( nType, ptP, ptM, dAng, nProcId, nNextId) ; // se previsto un prossimo punto, continuo if ( nNextId != 0) return true ; // costruisco il contorno libero PtrOwner pCrvCompo( CurveFromFces( m_FcData)) ; m_FcData.clear() ; if ( IsNull( pCrvCompo)) return false ; // se previsto, imposto spessore pCrvCompo->SetThickness( -m_dFcDepth) ; // verifico se curva chiusa bool bClosed = pCrvCompo->IsClosed() ; // verifico se gli estremi sono sul bordo della faccia Point3d ptStart ; pCrvCompo->GetStartPoint( ptStart) ; Point3d ptEnd ; pCrvCompo->GetEndPoint( ptEnd) ; bool bEndsOnCont = IsPointOnOrNearFaceContour( ptStart, true, nSide) && IsPointOnOrNearFaceContour( ptEnd, true, nSide) ; // verifico se interessa tutto lo spessore della trave perpendicolarmente alla faccia BBox3d b3Crv ; pCrvCompo->GetLocalBBox( b3Crv) ; bool bHCross = ( ! b3Crv.IsEmpty() && b3Crv.GetMax().z > - EPS_SMALL && b3Crv.GetMin().z < - GetSideHeight( nSide) + EPS_SMALL) ; // lo porto nel riferimento della faccia pCrvCompo->ToGlob( GetSideFrame( nSide)) ; // ricavo la spezzata che la approssima PolyLine PL ; if ( ! pCrvCompo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_STD, PL)) return false ; // creo la superficie di estrusione corrispondente PtrOwner pStm( CreateSurfTriMesh()) ; Vector3d vtExtr ; pCrvCompo->GetExtrusion( vtExtr) ; double dThick ; pCrvCompo->GetThickness( dThick) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, vtExtr * dThick)) return false ; if ( nGroup == 4) pStm->Invert() ; // se chiusa e con flag di svuotatura if ( bClosed && m_bFcPocket) { // creo la superficie di fondo PtrOwner pPocket( CreateSurfTriMesh()) ; if ( IsNull( pPocket) || ! pPocket->CreateByFlatContour( PL)) return false ; // la porto in posizione corretta pPocket->Translate( vtExtr * dThick) ; // la unisco alla parte laterale pStm->DoSewing( *pPocket) ; } // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; // 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 ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCompo)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiusto l'outline se spessore come trave if ( UseProcessToTrimOutline( nId) && (( bEndsOnCont && bHCross) || ( bClosed && m_bFcPocket))) TrimOutline( nId) ; 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::TrimPolygons( Polygon3d& plyP1, Polygon3d& plyP2, bool bInVsOut, bool bOnEq) { return ( plyP1.Trim( plyP2, bInVsOut, bOnEq) && plyP2.Trim( plyP1, bInVsOut, bOnEq)) ; } //---------------------------------------------------------------------------- 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::TrimSurfTmWithBox( ISurfTriMesh* pStm) { // verifico esistenza superficie if ( pStm == nullptr) return false ; // 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) ; } return true ; } //---------------------------------------------------------------------------- bool BtlGeom::TrimFlatCurveWithBox( ICurve* pCurve) { // verifico esistenza curva if ( pCurve == nullptr) return false ; // determino il piano della curva Plane3d plPlane ; if ( ! pCurve->IsFlat( plPlane, 10 * EPS_SMALL)) return false ; // determino la parte di piano (poligono) compresa nel box della trave Polygon3d Polyg ; if ( ! Polyg.FromPlaneTrimmedWithBox( plPlane, ORIG, ORIG + m_vtDim)) return false ; // creo la regione corrispondente PtrOwner pCrv( CreateCurveComposite()) ; if ( IsNull( pCrv) || ! pCrv->FromPolyLine( Polyg.GetPolyLine())) return false ; PtrOwner pSfr( CreateSurfFlatRegion()) ; if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pCrv))) return false ; // calcolo la classificazione della curva rispetto alla regione CRVCVECTOR ccClass ; if ( ! pSfr->GetCurveClassification( *pCurve, ccClass)) return false ; // determino gli intervalli di curva da conservare Intervals inOk ; for ( auto& ccOne : ccClass) { if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M) inOk.Add( ccOne.dParS, ccOne.dParE) ; } // se curva aperta if ( ! pCurve->IsClosed()) { // considero solo min-max degli intervalli if ( inOk.GetCount() >= 1) { // eseguo il taglio double dParS, dParE ; inOk.GetMinMax( dParS, dParE) ; return pCurve->TrimStartEndAtParam( dParS, dParE) ; } } // altrimenti curva chiusa else { // se c'è un solo intervallo valido if ( inOk.GetCount() == 1) { // eseguo il taglio double dParS, dParE ; inOk.GetFirst( dParS, dParE) ; return pCurve->TrimStartEndAtParam( dParS, dParE) ; } // se ci sono due intervalli a cavallo del punto di giunzione if ( inOk.GetCount() == 2) { // recupero il dominio della curva double dStart, dEnd ; pCurve->GetDomain( dStart, dEnd) ; double dParS1, dParE1 ; inOk.GetFirst( dParS1, dParE1) ; double dParS2, dParE2 ; inOk.GetNext( dParS2, dParE2) ; if ( abs( dParS1 - dStart) < EPS_SMALL && abs( dParE2 - dEnd) < EPS_SMALL) return pCurve->TrimStartEndAtParam( dParS2, dParE1) ; } } return false ; } //---------------------------------------------------------------------------- ICurveComposite* BtlGeom::CurveFromFces( const FCEDEQUE& dqFce, int nStartInd) { // verifico validità indice di inizio if ( nStartInd < 0 || nStartInd >= int( dqFce.size())) return nullptr ; // verifico validità tipo di inizio if ( dqFce[nStartInd].nType != FreeContourEnt::START && dqFce[nStartInd].nType != FreeContourEnt::START_CNT0 && dqFce[nStartInd].nType != FreeContourEnt::START_CNT1) return nullptr ; // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return nullptr ; // recupero le entità free contour for ( size_t i = nStartInd + 1 ; i < dqFce.size() ; ++ i) { // se retta if ( dqFce[i].nType == FreeContourEnt::LINE) { // creo e setto la retta PtrOwner pCrvLine( CreateCurveLine()) ; if ( IsNull( pCrvLine) || ! pCrvLine->Set( dqFce[i-1].ptP, dqFce[i].ptP)) return nullptr ; // inserisco la linea nella curva composta if ( ! pCrvCompo->AddCurve( ::Release( pCrvLine))) return nullptr ; } // altrimenti arco else if ( dqFce[i].nType == FreeContourEnt::ARC) { // creo e setto l'arco (se i punti sono allineati è un segmento di retta) PtrOwner pCrv ; if ( ! pCrv.Set( GetArc3P( dqFce[i-1].ptP, dqFce[i].ptM, dqFce[i].ptP, false))) return nullptr ; // inserisco l'arco nella curva composta if ( ! pCrvCompo->AddCurve( Release( pCrv))) return nullptr ; } // altrimenti curva terminata else break ; } // imposto versore estrusione pCrvCompo->SetExtrusion( Z_AX) ; return Release( pCrvCompo) ; } //--------------------------------------------------------------------------- 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 ; } //--------------------------------------------------------------------------- bool BtlGeom::SetAuxId( int nId, const INTVECTOR& vnAuxId) { if ( nId == GDB_ID_NULL) return false ; // inserisco chiave con Id di geometrie ausiliarie m_pGDB->SetInfo( nId, IKEY_AUXID, vnAuxId) ; return true ; }