//---------------------------------------------------------------------------- // EgalTech 2015-2021 //---------------------------------------------------------------------------- // File : BtlGeomProc.cpp Data : 26.08.21 Versione : 2.3h2 // 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. // 10.01.20 DS Agg. import Block House Half Lap. // 18.02.20 DS Corr. import BirdsMouth. // 31.03.20 DS Agg. import TriangleCut, TyroleanDovetail e Dovetail. // 04.04.20 DS Agg. import Hip or Valley Rafter Notch. // 02.06.20 DS Agg. gestione fori aggiuntivi delle feature che li prevedono. // 05.10.20 DS Corr. gestione P04 con P11 nullo in LongitudinalCut e RidgeValleyCut. // 26.08.21 DS Agg. import variant (0/1/2/3/4-900-X). // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DllMain.h" #include "BtlGeom.h" #include "/EgtDev/Include/EGkAngle.h" #include "/EgtDev/Include/EGkGeoVector3d.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/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLineBox.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" #include "/EgtDev/Include/EgkGeoPoint3d.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_SAW_CUT( nG, nP) ( ( nGroup == 0 || nGroup == 3 || nGroup == 4) && nProc == 13) #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_RAFTER_NOTCH( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 25) #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_LOGHOUSE_HL2( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 33) #define IS_SEATHING_CUT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 34) #define IS_FRENCH_RIDGELAP( nG, nP) ( ( nGroup == 1 || nGroup == 2) && nProc == 35) #define IS_CHAMFER( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 36) #define IS_LOGHOUSE_HL4( nG, nP) ( ( nGroup == 4) && nProc == 37) #define IS_LOGHOUSE_FRONT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 38) #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 == 1 || nGroup == 2 || 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_PLANING( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 90) #define IS_PROF_FRONT( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 100) #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_PROF_HEAD( nG, nP) ( ( nGroup == 3 || nGroup == 4) && nProc == 106) #define IS_ROUND_ARCH( nG, nP) ( ( nGroup == 4) && nProc == 104) #define IS_TRIANGLE_CUT( nG, nP) ( ( nGroup == 4) && nProc == 120) #define IS_TYROLEAN_DOVETAIL( nG, nP) ( ( nGroup == 1 || nGroup == 2 || nGroup == 3 || nGroup == 4) && nProc == 136) #define IS_DOVETAIL( nG, nP) ( ( nGroup == 1 || nGroup == 2 || nGroup == 3 || nGroup == 4) && nProc == 138) #define IS_FREE_CONTOUR( nG, nP) ( ( nGroup == 0 || nGroup == 3 || nGroup == 4) && (nProc == 250 || nProc == 251 || nProc == 252)) #define IS_VARIANT( nG, nP) ( ( nGroup == 0 || nGroup == 1 || nGroup == 2 || nGroup == 3 || nGroup == 4) && nProc == 900) //---------------------------------------------------------------------------- const double COS_ALMOST_PERP = cos( 85. * DEGTORAD) ; const double TOL_OPEN_DRILL = 1.0 ; const double TOL_DRILL_H_T = 10.0 ; const double LEN_EXTRUS_AGG = 50. ; const double BULGE_90D = tan( 90.0 / 4 * DEGTORAD) ; const double PEN_DEPTH = 5.0 ; const double NAILING_DEPTH = 10.0 ; const double LOCKOUT_DEPTH = 0.1 ; //---------------------------------------------------------------------------- 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; return true ; } // se taglio di lama if ( IS_SAW_CUT( 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( 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( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0.5 * GetSideWidth( nSide)) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( GetSideLength( nSide)) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; return true ; } // se tacca cantonale if ( IS_RAFTER_NOTCH( 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( 5) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 7) ; vdPar.emplace_back( 45) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 30) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 20) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; return true ; } // se mezzo legno per block haus (2 scassi) if ( IS_LOGHOUSE_HL2( nGroup, nProc)) { vnDPar.reserve( 5) ; vdPar.reserve( 6) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 6) ; 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( GetSideWidth( nSide)) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; return true ; } // se giunzione francese if ( IS_FRENCH_RIDGELAP( nGroup, nProc)) { vnDPar.reserve( 4) ; vdPar.reserve( 4) ; 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( 13) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; return true ; } // se mezzo legno per block haus (4 scassi) if ( IS_LOGHOUSE_HL4( nGroup, nProc)) { vnDPar.reserve( 16) ; vdPar.reserve( 16) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; 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( 8) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 100) ; vnDPar.emplace_back( 16) ; vdPar.emplace_back( GetSideHeight( nSide) / 2) ; vnDPar.emplace_back( 17) ; vdPar.emplace_back( GetSideHeight( nSide)) ; vnDPar.emplace_back( 18) ; vdPar.emplace_back( GetSideHeight( nSide)) ; vnDPar.emplace_back( 19) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.clear() ; return true ; } // se giunzione frontale per block haus if ( IS_LOGHOUSE_FRONT( 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( 6) ; vdPar.emplace_back( 90) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 15) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 10) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 25) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 100) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; return true ; } // se piallatura if ( IS_PLANING( nGroup, nProc)) { vnDPar.reserve( 4) ; vdPar.reserve( 4) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 15) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( GetSideLength( nSide)) ; nSPar = 0 ; sPar.clear() ; return true ; } // se profilo frontale if ( IS_PROF_FRONT( nGroup, nProc)) { vnDPar.reserve( 7) ; vdPar.reserve( 7) ; vnDPar.emplace_back( 1) ; 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( 0) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 250) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 250) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; 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.clear() ; 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.clear() ; return true ; } // se testa profilata if ( IS_PROF_HEAD( nGroup, nProc)) { vnDPar.reserve( 16) ; vdPar.reserve( 16) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 10) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0.3 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 0.3 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 16) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 17) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 18) ; vdPar.emplace_back( 0.3 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 19) ; vdPar.emplace_back( 0.3 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 20) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 21) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 22) ; vdPar.emplace_back( 0.1 * GetSideHeight( nSide)) ; nSPar = 0 ; sPar.clear() ; 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.clear() ; return true ; } // se taglio a triangolo if ( IS_TRIANGLE_CUT( 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( 10) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 1) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( -1) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( 1) ; nSPar = 0 ; sPar.clear() ; return true ; } // se incastro tirolese if ( IS_TYROLEAN_DOVETAIL( nGroup, nProc)) { vnDPar.reserve( 15) ; vdPar.reserve( 15) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 30) ; vnDPar.emplace_back( 3) ; vdPar.emplace_back( 0.5 * GetSideHeight( 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( 0) ; vnDPar.emplace_back( 8) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 15) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0.25 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 13) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( GetSideWidth( nSide)) ; vnDPar.emplace_back( 16) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.clear() ; return true ; } // se incastro coda di rondine if ( IS_DOVETAIL( nGroup, nProc)) { vnDPar.reserve( 11) ; vdPar.reserve( 11) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 30) ; vnDPar.emplace_back( 3) ; vdPar.emplace_back( 0.5 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 4) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 5) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 9) ; vdPar.emplace_back( 15) ; vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0.333 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0.167 * GetSideHeight( nSide)) ; vnDPar.emplace_back( 14) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 15) ; vdPar.emplace_back( GetSideWidth( nSide)) ; vnDPar.emplace_back( 16) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.clear() ; return true ; } // se contorno libero if ( IS_FREE_CONTOUR( 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( 5) ; vdPar.emplace_back( GetSideHeight( nSide)) ; vnDPar.emplace_back( 6) ; vdPar.emplace_back( FC_SIDEANG_NONE) ; 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) ; 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.clear() ; return true ; } // se variante if ( IS_VARIANT( nGroup, nProc)) { vnDPar.reserve( 2) ; vdPar.reserve( 2) ; vnDPar.emplace_back( 1) ; vdPar.emplace_back( 0) ; vnDPar.emplace_back( 2) ; vdPar.emplace_back( 0) ; nSPar = 0 ; sPar.clear() ; 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, const STRVECTOR& vsUAtt, int nLine) { // salvo numero di linea del file in cui è definito il processo m_nBtlLine = nLine ; // reset dell'identificativo della geometria principale della feature m_nProcId = GDB_ID_NULL ; // se taglio if ( IS_CUT( nGroup, nProc)) return AddCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se taglio longitudinale if ( IS_LONGIT_CUT( nGroup, nProc)) return AddLongitCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se doppio taglio if ( IS_DOUBLE_CUT( nGroup, nProc)) return AddDoubleCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se doppio taglio longitudinale if ( IS_RIDGEVALLEY_CUT( nGroup, nProc)) return AddRidgeValleyCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se taglio di lama if ( IS_SAW_CUT( nGroup, nProc)) return AddSawCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se scanalatura if ( IS_SLOT( nGroup, nProc)) return AddSlot( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se scanalatura frontale if ( IS_FRONT_SLOT( nGroup, nProc)) return AddFrontSlot( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se tacca if ( IS_BIRDS_MOUTH( nGroup, nProc)) return AddBirdsMouth( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se tacca cantonale if ( IS_RAFTER_NOTCH( nGroup, nProc)) return AddRafterNotch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se mezzo-legno di testa if ( IS_RIDGE_LAP( nGroup, nProc)) return AddRidgeLap( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se mezzo-legno if ( IS_LAP_JOINT( nGroup, nProc)) return AddLapJoint( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se intaglio if ( IS_NOTCH( nGroup, nProc)) return AddNotch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se mezzolegno blockhaus (2 scassi) if ( IS_LOGHOUSE_HL2( nGroup, nProc)) return AddLogHouseHL2( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se taglio per rivestimento if ( IS_SEATHING_CUT( nGroup, nProc)) return AddSeathingCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se giunzione francese if ( IS_FRENCH_RIDGELAP( nGroup, nProc)) return AddFrenchRidgeLap( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se smusso if ( IS_CHAMFER( nGroup, nProc)) return AddChamfer( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se mezzo legno per block haus (4 scassi) if ( IS_LOGHOUSE_HL4( nGroup, nProc)) return AddLogHouseHL4( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se giunzione frontale per block haus if ( IS_LOGHOUSE_FRONT( nGroup, nProc)) return AddLogHouseFront( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se tasca if ( IS_POCKET( nGroup, nProc)) return AddPocket( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se foratura if ( IS_DRILL( nGroup, nProc)) return AddDrill( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se tenone if ( IS_TENON( nGroup, nProc)) return AddTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se mortasa if ( IS_MORTISE( nGroup, nProc)) return AddMortise( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se mortasa sul fronte if ( IS_MORTISE_FRONT( nGroup, nProc)) return AddMortiseFront( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se avanzamento tenone if ( IS_HOUSE( nGroup, nProc)) { nGroup = ( nGroup == 1 || nGroup == 3 ? 1 : 2) ; return AddTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; } // se avanzamento mortasa if ( IS_HOUSE_MORTISE( nGroup, nProc)) return AddMortise( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se tenone a coda di rondine if ( IS_DOVETAIL_TENON( nGroup, nProc)) return AddDovetailTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se mortasa a coda di rondine if ( IS_DOVETAIL_MORTISE( nGroup, nProc)) return AddDovetailMortise( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se mortasa a coda di rondine sul fronte if ( IS_DTMORTISE_FRONT( nGroup, nProc)) return AddDtMortiseFront( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se marcatura if ( IS_MARKING( nGroup, nProc)) return AddMarking( nGroup, nProc, nSide, sDes, nProcId, vnDPar, nSPar, vdPar, sPar, vsUAtt) ; // se testo if ( IS_TEXT( nGroup, nProc)) return AddText( nGroup, nProc, nSide, sDes, nProcId, vnDPar, nSPar, vdPar, sPar, vsUAtt) ; // se giunto gerber if ( IS_SIMPLESCARF( nGroup, nProc)) return AddSimpleScarf( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se giunto a dardo if ( IS_SCARFJOINT( nGroup, nProc)) return AddScarfJoint( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // incastro dietro if ( IS_STEPJOINT( nGroup, nProc)) return AddStepJoint( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se incastro semplice if ( IS_STEPJOINTNOTCH( nGroup, nProc)) return AddStepJointNotch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se piallatura if ( IS_PLANING( nGroup, nProc)) return AddPlaning( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se profilo frontale if ( IS_PROF_FRONT( nGroup, nProc)) return AddProfileFront( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se profilo concavo if ( IS_PROF_HEADCONCAVE( nGroup, nProc)) return AddProfileHeadCoCo( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se profilo convesso if ( IS_PROF_HEADCONVEX( nGroup, nProc)) return AddProfileHeadCoCo( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se profilo caudato if ( IS_PROF_HEADCAMBERED( nGroup, nProc)) return AddProfileHeadCambered( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se testa profilata if ( IS_PROF_HEAD( nGroup, nProc)) return AddProfileHead( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se arco if ( IS_ROUND_ARCH( nGroup, nProc)) return AddRoundArch( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se taglio a triangolo if ( IS_TRIANGLE_CUT( nGroup, nProc)) return AddTriangleCut( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se incastro tirolese if ( IS_TYROLEAN_DOVETAIL( nGroup, nProc)) return AddTyroleanDovetail( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se incastro a coda di rondine if ( IS_DOVETAIL( nGroup, nProc)) return AddDovetail( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; // se contorno libero if ( IS_FREE_CONTOUR( nGroup, nProc)) return AddFreeContour( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // se variante if ( IS_VARIANT( nGroup, nProc)) return AddVariant( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; return false ; } //---------------------------------------------------------------------------- bool BtlGeom::AddCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 5) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], -vdPar[2]) ; // P01, P02, P03 double dAngle = Clamp( vdPar[3], 0.1, 179.9) ; // P06 double dInclination = Clamp( vdPar[4], 0.1, 179.9) ; // P07 // 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 ; if ( plyCut.GetSideCount() < 3) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // creo la trimesh con questo contorno PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByFlatContour( plyCut.GetPolyLine())) return false ; // calcolo la direttrice di questa superficie rigata (se ortogonale all'asse della trave entrambe) PtrOwner pCrv ; if ( abs( dInclination - ANG_RIGHT) < EPS_SMALL) { int nAdjSide = ( nSide + 1 <= 4 ? nSide + 1 : 1) ; Vector3d vtNorm ; pStm->GetFacetNormal( 0, vtNorm) ; Vector3d vtExtr = GetSideVersN( nAdjSide) ^ vtNorm ; pCrv.Set( GetDirectrixOfRuledSurf( pStm, vtExtr)) ; if ( IsNull( pCrv)) return false ; // imposto estrusione e spessore pCrv->SetExtrusion( vtExtr) ; pCrv->SetThickness( -GetSideWidth( nAdjSide)) ; } PtrOwner pCrv2 ; if ( abs( dAngle - ANG_RIGHT) < EPS_SMALL) { Vector3d vtNorm ; pStm->GetFacetNormal( 0, vtNorm) ; Vector3d vtExtr = GetSideVersN( nSide) ^ vtNorm ; pCrv2.Set( GetDirectrixOfRuledSurf( pStm, vtExtr)) ; if ( IsNull( pCrv2)) return false ; // imposto estrusione e spessore pCrv2->SetExtrusion( vtExtr) ; pCrv2->SetThickness( -GetSideWidth( nSide)) ; } // 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 le curve nel DB geometrico int nTId = GDB_ID_NULL ; if ( ! IsNull( pCrv)) { nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrv)) ; if ( nTId == GDB_ID_NULL) return false ; } int nT2Id = GDB_ID_NULL ; if ( ! IsNull( pCrv2)) { nT2Id = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrv2)) ; if ( nT2Id == 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId, nT2Id}) ; // eseguo trim con outline (se richiesto) TrimProcessWithOutline( nId) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLongitCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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] ; if ( dLength < EPS_SMALL && nLimits != 0) dLength = m_vtDim.x - dStart ; // calcolo la normale alla faccia del taglio Vector3d vtN = FromSpherical( 1, dInclination, - 90) ; if ( ( nGroup == 3 && dInclination > 0) || ( nGroup == 4 && dInclination < 0)) vtN.Invert() ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; if ( plyCut.GetSideCount() < 3) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDoubleCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 ; if ( plyCut1.GetSideCount() < 3 && plyCut2.GetSideCount() < 3) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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( STM_COMPACT_APPROX) ; // calcolo la direttrice di questa superficie rigata PtrOwner pCrv ; if ( abs( dInclination1 - ANG_RIGHT) < EPS_SMALL && abs( dInclination2 - ANG_RIGHT) < EPS_SMALL) { int nAdjSide = ( nSide + 1 <= 4 ? nSide + 1 : 1) ; Vector3d vtNorm ; pStm->GetFacetNormal( 0, vtNorm) ; Vector3d vtExtr = GetSideVersN( nAdjSide) ^ vtNorm ; pCrv.Set( GetDirectrixOfRuledSurf( pStm, vtExtr)) ; if ( IsNull( pCrv)) return false ; // imposto estrusione e spessore pCrv->SetExtrusion( vtExtr) ; pCrv->SetThickness( -GetSideWidth( nAdjSide)) ; } // 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 = GDB_ID_NULL ; if ( ! IsNull( pCrv)) { nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrv)) ; if ( nTId == 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddRidgeValleyCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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] ; if ( dLength < EPS_SMALL && nLimits != 0) dLength = m_vtDim.x - dStart ; 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( 1, -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 ; if ( plyCut1.GetSideCount() < 3 && plyCut2.GetSideCount() < 3) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // faccia longitudinale di servizio di separazione tra i tagli Polygon3d plyLong ; if ( ! CreatePolygonInBox( Point3d( 0, dMid, 0), -Y_AX, nSide, plyLong, EPS_SMALL)) 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 ; Polygon3d 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 ; Polygon3d 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, plyCut2) || ! DoSewing( pStm, plyStart1) || ! DoSewing( pStm, plyStart2) || ! DoSewing( pStm, plyEnd1) || ! DoSewing( pStm, plyEnd2)) return false ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddSawCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 8) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], -vdPar[2]) ; // P01, P02, P03 double dAngle = Clamp( vdPar[3], -180., 180.) ; // P06 double dInclination = Clamp( vdPar[4], 0.1, 179.9) ; // P07 double dBevel = Clamp( vdPar[5], -89.9, 89.9) ; // P08 double dDepth = Clamp( vdPar[6], 1., 50000.) ; // P11 double dLength = Clamp( vdPar[7], 0., 100000.) ; // P12 if ( dLength < EPS_SMALL) dLength = GetSideLength( nSide) + GetSideWidth( nSide) ; // costruzione della normale della faccia Vector3d vtN = FromSpherical( 1, dInclination, -90 - dAngle) ; // riferimento della faccia in locale al lato (asse X orizzontale e Y più inclinato) Vector3d vtX = FromUprightOrtho( vtN) ^ vtN ; Frame3d frCut ; frCut.Set( ptP, vtN, vtX) ; // riferimento del lato Frame3d frRef = GetSideFrame( nSide) ; // punto in basso Point3d ptQ = ptP - frCut.VersY() * dDepth / frCut.VersY().z ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; // piano di limitazione Xp locale Plane3d plXp ; plXp.Set( ptP, frCut.VersX()) ; // piano di limitazione Xm locale Plane3d plXm = plXp ; plXm.Invert() ; plXm.Offset( dLength) ; // piano di limitazione Yp locale Plane3d plYp ; plYp.Set( ptP, frCut.VersY()) ; // piano di limitazione Ym locale Plane3d plYm = plYp ; plYm.Invert() ; plYm.Offset( dDepth / frCut.VersY().z) ; plYm.Rotate( ptQ, frCut.VersZ(), dBevel) ; // porto i piani in globale ed eseguo le limitazione plXp.ToGlob( frRef) ; if ( ! plyCut.Trim( plXp, true, true)) return false ; plXm.ToGlob( frRef) ; if ( ! plyCut.Trim( plXm, true, true)) return false ; plYp.ToGlob( frRef) ; if ( ! plyCut.Trim( plYp, true, true)) return false ; plYm.ToGlob( frRef) ; if ( ! plyCut.Trim( plYm, true, true)) return false ; // controllo poligono if ( plyCut.GetSideCount() < 3) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // se gruppo 3 lo inverto if ( nGroup == 3) plyCut.Invert() ; // creo il versore dal fondo verso l'alto della faccia Vector3d vtDir = frCut.VersY() ; vtDir.ToGlob( frRef) ; Point3d ptCen = plyCut.GetCentroid() ; PtrOwner pGvt( CreateGeoVector3d()) ; if ( IsNull( pGvt) || ! pGvt->Set( vtDir, ptCen)) 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 ; // inserisco il versore nel DB geometrico int nAuxId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pGvt)) ; if ( nAuxId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativo della geometria ausiliaria SetAuxId( nId, {nAuxId}) ; // non modifica l'outline m_pGDB->SetInfo( nId, IKEY_TRIM, 0) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddSlot( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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) ; Vector3d vtN2 = - Z_AX ; Vector3d vtN4 = - vtN2 ; vtN1.Rotate( X_AX, dInclEff - ANG_RIGHT) ; vtN3.Rotate( X_AX, dInclEff - ANG_RIGHT) ; vtNf.Rotate( X_AX, dInclEff - ANG_RIGHT) ; vtN2.Rotate( X_AX, dInclEff) ; vtN4.Rotate( X_AX, dInclEff) ; 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 ; // costruzione vettore longitudinale faccia di fondo Vector3d vtEl = vtNf ^ vtEo ; vtEl.Normalize() ; // 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) ; vtEl.Rotate( Y_AX, dRotAng) ; } // gestione riferimento if ( ! IsGlobFrame( frRef)) { ptP.ToGlob( frRef) ; vtN1.ToGlob( frRef) ; vtN2.ToGlob( frRef) ; vtN3.ToGlob( frRef) ; vtN4.ToGlob( frRef) ; vtNf.ToGlob( frRef) ; vtEv.ToGlob( frRef) ; vtEo.ToGlob( frRef) ; vtEl.ToGlob( frRef) ; } // 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 + vtEl * ( dLength / ( vtN1 * vtEl)), vtN3, nSide, plyFace3)) return false ; Polygon3d plyFace4 ; if ( ! CreatePolygonInBox( ptB - vtEo * dThick / 2, vtN4, nSide, plyFace4)) return false ; // trimmo tra loro le facce POLYGVECTOR vPolyg{ plyFaceF, plyFace1, plyFace2, plyFace3, plyFace4} ; INTMATRIX vAdjac{ { 1, 2, 3, 4}, { 0, 2, 4}, { 0, 1, 3}, { 0, 2, 4}, { 0, 1, 3}} ; if ( ! TrimConcaveFaces( vPolyg, vAdjac)) return false ; // creo la trimesh dalle facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; for ( int i = 0 ; i < int( vPolyg.size()) ; ++ i) DoSewing( pStm, vPolyg[i]) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddFrontSlot( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 (piccolo incremento per evitare problemi da arrotondamenti in BTL) double dMortHL = 0.5 * dMortL + 10 * EPS_SMALL ; double dMortHW = 0.5 * dMortW + 10 * EPS_SMALL ; PolyLine PL ; PL.AddUPoint( 0, Point3d( - dMortHW, dMortHL, 0)) ; PL.AddUPoint( 1, Point3d( - dMortHW, - dMortHL, 0)) ; PL.AddUPoint( 2, Point3d( dMortHW, - dMortHL, 0)) ; PL.AddUPoint( 3, 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 di taglio PtrOwner pCut ; // 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 della mortasa SurfFlatRegionByContours SfrMrt ; SfrMrt.AddCurve( pCompo->Clone()) ; PtrOwner pMrt( SfrMrt.GetSurf()) ; if ( IsNull( pMrt)) return false ; // sottraggo la regione della mortasa da quella esterna if ( ! pReg->Subtract( *pMrt)) return false ; // ne deduco la superficie trimesh const ISurfTriMesh* pAuxSrf = pReg->GetAuxSurf() ; if ( pAuxSrf != nullptr) { pCut.Set( pAuxSrf->Clone()) ; if ( IsNull( pCut)) return false ; } // verifico che la superficie di taglio sia da conservare bool bSave = false ; POLYLINEVECTOR vPL ; if ( ! IsNull( pCut) && pCut->GetFacetLoops( 0, vPL) && ! vPL.empty()) { if ( vPL.size() >= 1) vPL[0].RemoveAlignedPoints( 100 * EPS_SMALL) ; bSave = ( vPL.size() > 1 || vPL[0].GetLineNbr() > 6) ; if ( ! bSave) { Point3d ptS, ptE ; bool bLine = vPL[0].GetFirstLine( ptS, ptE) ; while ( bLine) { Point3d ptM = Media( ptS, ptE) ; BBox3d b3Beam( ORIG, ORIG + m_vtDim) ; b3Beam.Expand( -10 * EPS_SMALL) ; if ( b3Beam.Encloses( ptM)) { bSave = true ; break ; } bLine = vPL[0].GetNextLine( ptS, ptE) ; } } } if ( ! bSave) pCut.Reset() ; } // definisco la superficie della mortasa PtrOwner pStm( CreateSurfTriMesh()) ; // creo la superficie trimesh laterale della mortasa (un poco più lunga in alto, per evitare problemi con solidi) if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, - frMort.VersZ() * ( dMortD + ( IsNull( pCut) ? 100 * EPS_SMALL : 0)))) return false ; if ( IsNull( pCut)) pStm->Translate( frMort.VersZ() * 100 * EPS_SMALL) ; // creo la superficie trimesh di fondo della mortasa PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByFlatContour( PL)) return false ; pStmCap->Translate( - frMort.VersZ() * dMortD) ; pStm->DoSewing( *pStmCap) ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStm) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie trimesh della mortasa nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // se presente, inserisco la superficie trimesh del taglio nel DB geometrico int nCutId = GDB_ID_NULL ; if ( ! IsNull( pCut)) { nCutId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCut)) ; if ( nCutId == GDB_ID_NULL) return false ; // colore semitrasparente SetAlpha( nCutId, 80) ; // non usare direttamente nel trim m_pGDB->SetInfo( nCutId, IKEY_TRIM, 0) ; } // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie if ( nCutId != GDB_ID_NULL) SetAuxId( nId, {nCutId}) ; // se presente taglio, modifica l'outline con superficie composta if ( nCutId != GDB_ID_NULL) m_pGDB->SetInfo( nId, IKEY_TRIM, 2) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddBirdsMouth( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 ; // recupero il centro della linea (per eventuale foro) Point3d ptCen = Media( ptP, ptQ) ; // 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 ; // 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 ; } // 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 ; } // eventuale quinta faccia (limite di fronte) Vector3d vtN5 ; Polygon3d plyFace5 ; if ( abs( ptO.y) > EPS_SMALL) { // imposto la normale per faccia anti-parallela al fronte 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 ; } // 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 = - vtN5 ; // 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 ; } // trim tra queste facce POLYGVECTOR vPolyg{ plyFace1, plyFace2, plyFace3, plyFace4, plyFace5, plyFace6} ; INTMATRIX vAdjac{ { 1, 2, 4, 5}, { 0, 3, 4, 5}, { 0, 3, 4, 5}, { 1, 2, 4, 5}, { 0, 1, 2, 3}, { 0, 1, 2, 3}} ; if ( ! TrimConcaveFaces( vPolyg, vAdjac)) return false ; // creo la trimesh dalle facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; for ( int i = 0 ; i < int( vPolyg.size()) ; ++ i) DoSewing( pStm, vPolyg[i]) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // aggiungo eventuale foro if ( nFlag != 0 && ptCen.x > 10 * EPS_SMALL) { INTVECTOR vnDHoPar ; DBLVECTOR vdHoPar ; vnDHoPar.reserve( 7) ; vdHoPar.reserve( 7) ; vnDHoPar.emplace_back( 1) ; vdHoPar.emplace_back( ptCen.x) ; vnDHoPar.emplace_back( 2) ; vdHoPar.emplace_back( ptCen.y) ; vnDHoPar.emplace_back( 3) ; vdHoPar.emplace_back( 0) ; vnDHoPar.emplace_back( 6) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 7) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 11) ; vdHoPar.emplace_back( GetSideHeight( nSide)) ; vnDHoPar.emplace_back( 12) ; vdHoPar.emplace_back( 16) ; STRVECTOR vsHoUAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHoUAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHoUAtt.emplace_back( sUAtt) ; } vsHoUAtt.emplace_back( "\"DiamUser\":\"1\"") ; if ( ! AddDrill( nGroup, 40, nSide, sDes, nProcId, Frame3d(), vnDHoPar, vdHoPar, vsHoUAtt)) return false ; // riferimenti reciproci int nAdjId = m_nProcId ; SetMainAdjId( nId, { nAdjId}) ; } m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddRafterNotch( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 6) return false ; // sistemo i dati double dPos = Clamp( vdPar[0], -99999., 99999.) ; // P01 double dInside = Clamp( vdPar[1], -50000., 50000.) ; // P02 int nHole = lround( vdPar[2]) ; // P05 double dAng1 = Clamp( vdPar[3], 1., 179.) ; // P06 double dAng2 = Clamp( vdPar[4], 1., 179.) ; // P07 double dSlope = Clamp( vdPar[5], 0., 180.) ; // P08 double dDepth = Clamp( vdPar[6], 0., 50000.) ; // P11 double dWidth1 = Clamp( vdPar[7], 0., 50000.) ; // P14 double dWidth2 = Clamp( vdPar[8], 0., 50000.) ; // P15 if ( dWidth1 < EPS_SMALL) dWidth1 = 2000 ; if ( dWidth2 < EPS_SMALL) dWidth2 = 2000 ; // punto di riferimento Point3d ptP( dPos, dInside, -dDepth) ; // faccia di fondo Vector3d vtN = FromSpherical( 1, dSlope, ( nGroup == 3 ? 0 : 180)) ; Polygon3d plyBott ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyBott)) return false ; // prima faccia frontale Vector3d vtN1 = Y_AX ; vtN1.Rotate( vtN, ( nGroup == 3 ? dAng1 : -dAng1)) ; Polygon3d plyFront1 ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyFront1)) return false ; // seconda faccia frontale Vector3d vtN2 = -Y_AX ; vtN2.Rotate( vtN, ( nGroup == 3 ? -dAng2 : dAng2)) ; Polygon3d plyFront2 ; if ( ! CreatePolygonInBox( ptP, vtN2, nSide, plyFront2)) return false ; // prima faccia opposta Polygon3d plyOppo1 ; if ( ! CreatePolygonInBox( ptP + vtN1 * dWidth1, -vtN1, nSide, plyOppo1)) return false ; // seconda faccia opposta Polygon3d plyOppo2 ; if ( ! CreatePolygonInBox( ptP + vtN2 * dWidth2, -vtN2, nSide, plyOppo2)) return false ; // taglio tra loro le tre facce if ( dAng1 + dAng2 <= 180) { if ( ! plyFront1.Trim( plyFront2, false, true) || ! plyFront2.Trim( plyFront1, false, false)) return false ; if ( ! plyBott.Trim( plyFront1, false, true) || ! plyFront1.Trim( plyBott, false, false)) return false ; if ( ! plyBott.Trim( plyFront2, false, true) || ! plyFront2.Trim( plyBott, false, false)) return false ; } else { if ( ! plyFront1.Trim( plyFront2, true, true) || ! plyFront2.Trim( plyFront1, true, false)) return false ; Polygon3d plyBott2 = plyBott ; if ( ! plyBott.Trim( plyFront1, false, true) || ! plyFront1.Trim( plyBott, false, false)) return false ; if ( ! plyBott2.Trim( plyFront1, true, true)) return false ; if ( ! plyBott2.Trim( plyFront2, false, true) || ! plyFront2.Trim( plyBott2, false, false)) return false ; plyBott.Add( plyBott2) ; } if ( dAng1 + dAng2 >= 180) { if ( ! plyOppo1.Trim( plyOppo2, false, true) || ! plyOppo2.Trim( plyOppo1, false, false)) return false ; if ( ! plyBott.Trim( plyOppo1, false, true) || ! plyOppo1.Trim( plyBott, false, false)) return false ; if ( ! plyBott.Trim( plyOppo2, false, true) || ! plyOppo2.Trim( plyBott, false, false)) return false ; } else { if ( ! plyOppo1.Trim( plyOppo2, true, true) || ! plyOppo2.Trim( plyOppo1, true, false)) return false ; Polygon3d plyBott2 = plyBott ; if ( ! plyBott.Trim( plyOppo1, false, true) || ! plyOppo1.Trim( plyBott, false, false)) return false ; if ( ! plyBott2.Trim( plyOppo1, true, true)) return false ; if ( ! plyBott2.Trim( plyOppo2, false, true) || ! plyOppo2.Trim( plyBott2, false, false)) return false ; plyBott.Add( plyBott2) ; } // creo la trimesh con queste facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; if ( ! DoSewing( pStm, plyBott) || ! DoSewing( pStm, plyFront1) || ! DoSewing( pStm, plyFront2) || ! DoSewing( pStm, plyOppo1) || ! DoSewing( pStm, plyOppo2)) return false ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddRidgeLap( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 ; // recupero il centro della faccia 2 (per eventuale foro) Point3d ptCen = plyFace2.GetCentroid() ; // 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // aggiungo eventuale foro if ( dHoDiam > 10 * EPS_SMALL && ptCen.x > 10 * EPS_SMALL) { INTVECTOR vnDHoPar ; DBLVECTOR vdHoPar ; vnDHoPar.reserve( 7) ; vdHoPar.reserve( 7) ; vnDHoPar.emplace_back( 1) ; vdHoPar.emplace_back( ptCen.x) ; vnDHoPar.emplace_back( 2) ; vdHoPar.emplace_back( ptCen.y) ; vnDHoPar.emplace_back( 3) ; vdHoPar.emplace_back( 0) ; vnDHoPar.emplace_back( 6) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 7) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 11) ; vdHoPar.emplace_back( GetSideHeight( nSide)) ; vnDHoPar.emplace_back( 12) ; vdHoPar.emplace_back( dHoDiam) ; STRVECTOR vsHoUAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHoUAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHoUAtt.emplace_back( sUAtt) ; } if ( ! AddDrill( nGroup + 2, 40, nSide, sDes, nProcId, Frame3d(), vnDHoPar, vdHoPar, vsHoUAtt)) return false ; // riferimenti reciproci int nAdjId = m_nProcId ; SetMainAdjId( nId, { nAdjId}) ; } m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLapJoint( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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) ; // verifiche dei dati if ( dDepth < 10 * EPS_SMALL && abs( dSlope) < EPS_ANG_SMALL && abs( dInclination - ANG_RIGHT) < EPS_ANG_SMALL) dDepth = GetSideHeight( nSide) ; // 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) { Point3d ptQ = ptP ; AdjustPointForPlaneNearBoxVertex( ptQ, vtN1, nSide) ; if ( ! CreatePolygonInBox( ptQ, 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 ; AdjustPointForPlaneNearBoxVertex( ptQ, vtNr, nSide) ; if ( ! CreatePolygonInBox( ptQ, vtNr, nSide, plyStart)) return false ; } } VerifyPolygonSize( plyStart) ; // faccia di fine Polygon3d plyEnd ; if ( ( nGroup == 4 && (nFlag & 2) == 0) || ( nGroup == 3 && (nFlag & 1) == 0)) { Point3d ptQ = ptP + dLength * vtN1 ; AdjustPointForPlaneNearBoxVertex( ptQ, -vtN1, nSide) ; if ( ! CreatePolygonInBox( ptQ, - vtN1, nSide, plyEnd)) return false ; } VerifyPolygonSize( plyEnd) ; // 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 && (nFlag & 4) == 0) { Point3d ptQ = ptP ; AdjustPointForPlaneNearBoxVertex( ptQ, Y_AX, nSide) ; if ( ! CreatePolygonInBox( ptQ, Y_AX, nSide, plyFront)) return false ; } if ( dStartY + dWidth < GetSideWidth( nSide) - EPS_SMALL && (nFlag & 8) == 0) { Point3d ptQ = ptP + dWidth * Y_AX ; AdjustPointForPlaneNearBoxVertex( ptQ, - Y_AX, nSide) ; if ( ! CreatePolygonInBox( ptQ, - 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 ( ( nGroup == 3 && (nFlag & 4) != 0) || ( nGroup == 4 && (nFlag & 4) == 0)) { vtRef1f.Rotate( vtN3, 180 - dLeadAngle) ; vtRef1b.Rotate( vtN3, - dLeadAngle) ; } else { vtRef1f.Rotate( vtN3, dLeadAngle) ; vtRef1b.Rotate( vtN3, 180 + 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) { Point3d ptQ = ptP ; AdjustPointForPlaneNearBoxVertex( ptQ, vtN2f, nSide) ; CreatePolygonInBox( ptQ, 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) { Point3d ptQ = ptP + dDeltaX * X_AX + dWidth * Y_AX ; AdjustPointForPlaneNearBoxVertex( ptQ, vtN2b, nSide) ; CreatePolygonInBox( ptQ, vtN2b, nSide, plyBack) ; } vtN2 = vtN2f ; } VerifyPolygonSize( plyFront) ; VerifyPolygonSize( plyBack) ; // faccia sopra Polygon3d plyTop ; if ( dStartZ < - EPS_SMALL && (nFlag & 32) == 0) { Point3d ptQ = ptP ; AdjustPointForPlaneNearBoxVertex( ptQ, -Z_AX, nSide) ; if ( ! CreatePolygonInBox( ptQ, -Z_AX, nSide, plyTop)) return false ; VerifyPolygonSize( plyTop) ; } // faccia di fondo Polygon3d plyBottom ; Vector3d vtEdge = ( plyFront.GetSideCount() > 0 ? vtN1 ^ vtN2 : vtN1 ^ Y_AX) ; vtEdge.Normalize() ; double dDist = dDepth / vtEdge.z ; if ( (nFlag & 16) == 0) { Point3d ptQ = ptP - dDist * vtEdge ; AdjustPointForPlaneNearBoxVertex( ptQ, vtN3, nSide) ; if ( ! CreatePolygonInBox( ptQ, vtN3, nSide, plyBottom)) return false ; VerifyPolygonSize( plyBottom) ; } // verifico tra loro le facce double dMatMin = min( 0.5 * dDepth, FACE_MIN_BACK_MAT) ; if ( ! VerifyPolygonWithPolygons( plyStart, plyFront, plyBack, plyTop, plyBottom, false, dMatMin)) plyStart.Clear() ; if ( ! VerifyPolygonWithPolygons( plyEnd, plyFront, plyBack, plyTop, plyBottom, false, dMatMin)) plyEnd.Clear() ; if ( ! VerifyPolygonWithPolygons( plyFront, plyStart, plyEnd, plyTop, plyBottom, false, dMatMin)) plyFront.Clear() ; if ( ! VerifyPolygonWithPolygons( plyBack, plyStart, plyEnd, plyTop, plyBottom, false, dMatMin)) plyBack.Clear() ; if ( ! VerifyPolygonWithPolygons( plyTop, plyStart, plyEnd, plyFront, plyBack, false, dMatMin)) plyTop.Clear() ; if ( ! VerifyPolygonWithPolygons( plyBottom, plyStart, plyEnd, plyFront, plyBack, false, dMatMin)) plyBottom.Clear() ; // trim tra queste facce POLYGVECTOR vPolyg{ plyStart, plyEnd, plyFront, plyBack, plyTop, plyBottom} ; INTMATRIX vAdjac{ { 2, 3, 4, 5}, { 2, 3, 4, 5}, { 0, 1, 4, 5}, { 0, 1, 4, 5}, { 0, 1, 2, 3}, { 0, 1, 2, 3}} ; if ( ! TrimConcaveFaces( vPolyg, vAdjac)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; for ( int i = 0 ; i < int( vPolyg.size()) ; ++ i) DoSewing( pStm, vPolyg[i]) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // eseguo trim con outline (se richiesto) TrimProcessWithOutline( nId) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddNotch( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - dDepth * Z_AX, Z_AX, nSide, plyBottom)) return false ; // trim tra le 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 ; 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 ; // 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLogHouseHL2( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 5) return false ; // sistemo i dati Point3d ptP( vdPar[0], 0, 0) ; // P01 double dAngle = Clamp( vdPar[1], 0.1, 179.9) ; // P06 double dDepth1 = Clamp( vdPar[2], 0., GetSideHeight( nSide)) ; // P11 double dDepth2 = Clamp( vdPar[3], 0., GetSideHeight( nSide)) ; // P12 double dLength = Clamp( vdPar[4], 1., 50000.) ; // P13 // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = FromSpherical( 1, 90, 90 - dAngle) ; if ( nGroup == 3) vtN1.Mirror( X_AX) ; if ( ! CreatePolygonInBox( ( ptP - vtN1 * dLength / 2), vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength / 2), -vtN1, nSide, plyEnd)) return false ; // se va fatto sulla faccia di riferimento int nGeom1Id = GDB_ID_NULL ; if ( dDepth1 > EPS_SMALL) { // copio le facce iniziale e finale Polygon3d plyStart1 = plyStart ; Polygon3d plyEnd1 = plyEnd ; // faccia di fondo Polygon3d plyBottom1 ; if ( ! CreatePolygonInBox( ptP - dDepth1 * Z_AX, Z_AX, nSide, plyBottom1)) return false ; // trim tra le facce if ( ! plyStart1.Trim( plyBottom1, false, true) || ! plyBottom1.Trim( plyStart1, false, false)) return false ; if ( ! plyEnd1.Trim( plyBottom1, false, true) || ! plyBottom1.Trim( plyEnd1, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyStart1) ; DoSewing( pStm, plyEnd1) ; DoSewing( pStm, plyBottom1) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; nGeom1Id = nId ; } // se va fatto sulla faccia opposta a quella di riferimento int nGeom2Id = GDB_ID_NULL ; if ( dDepth2 > EPS_SMALL) { // copio le facce iniziale e finale Polygon3d plyStart2 = plyStart ; Polygon3d plyEnd2 = plyEnd ; // faccia di fondo Polygon3d plyBottom2 ; if ( ! CreatePolygonInBox( ptP - ( GetSideHeight( nSide) - dDepth2) * Z_AX, -Z_AX, nSide, plyBottom2)) return false ; // trim tra le facce if ( ! plyStart2.Trim( plyBottom2, false, true) || ! plyBottom2.Trim( plyStart2, false, false)) return false ; if ( ! plyEnd2.Trim( plyBottom2, false, true) || ! plyBottom2.Trim( plyEnd2, false, false)) return false ; // creo la trimesh con questi contorni PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyStart2) ; DoSewing( pStm, plyEnd2) ; DoSewing( pStm, plyBottom2) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; nGeom2Id = nId ; } // se non è stata inserita alcuna geometria if ( nGeom1Id == GDB_ID_NULL && nGeom2Id == GDB_ID_NULL) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // assegnazione geometria principale m_nProcId = ( ( nGeom1Id != GDB_ID_NULL) ? nGeom1Id : nGeom2Id) ; // eventuali riferimenti reciproci if ( nGeom1Id != GDB_ID_NULL && nGeom2Id != GDB_ID_NULL) SetMainAdjId( nGeom1Id, { nGeom2Id}) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddSeathingCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddFrenchRidgeLap( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 4) return false ; // sistemo i dati double dPos = vdPar[0] ; // P01 int nFlag = lround( vdPar[1]) ; // P02 double dAngle = Clamp( vdPar[2], 0.1, 179.9) ; // P06 double dHoDiam = Clamp( vdPar[3], 0., 1000.) ; // P13 // punto di riferimento Point3d ptP( dPos, ( nFlag == 0 ? 0 : GetSideWidth( nSide)), - GetSideHeight( nSide) / 2) ; // versore facce di testa Vector3d vtN1 = FromSpherical( 1, 90, 90 + dAngle) ; if ( nFlag == 1) vtN1.Mirror( Y_AX) ; if ( nGroup == 1) vtN1.Mirror( X_AX) ; // faccia di testa Polygon3d plyStart ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyStart)) return false ; // faccia finale Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ptP - vtN1 * GetSideWidth( nSide), vtN1, nSide, plyEnd)) return false ; // faccia intermedia Vector3d vtV1 = - X_AX * GetSideWidth( nSide) / vtN1.x ; Vector3d vtV2 = vtV1 ; if ( ( nGroup == 2 && nFlag == 0) || ( nGroup == 1 && nFlag == 1)) vtV2.Rotate( Z_AX, dAngle) ; else vtV2.Rotate( Z_AX, - dAngle) ; vtV1 -= Z_AX * GetSideHeight( nSide) / 6 ; vtV2 += Z_AX * GetSideHeight( nSide) / 6 ; Vector3d vtN2 = vtV1 ^ vtV2 ; vtN2.Normalize() ; if ( vtN2.z < 0) vtN2.Invert() ; Polygon3d plyMid ; if ( ! CreatePolygonInBox( ptP, vtN2, nSide, plyMid)) return false ; // trim tra le facce if ( ! plyStart.Trim( plyMid, true, true) || ! plyMid.Trim( plyStart, true, false)) return false ; if ( ! plyEnd.Trim( plyMid, false, true) || ! plyMid.Trim( plyEnd, false, false)) return false ; // recupero il centro della faccia intermedia (per eventuale foro) Point3d ptCen = plyMid.GetCentroid() ; // creo la trimesh con queste facce PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyEnd) ; DoSewing( pStm, plyMid) ; DoSewing( pStm, plyStart) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // aggiungo eventuale foro if ( dHoDiam > 10 * EPS_SMALL && ptCen.x > 10 * EPS_SMALL) { INTVECTOR vnDHoPar ; DBLVECTOR vdHoPar ; vnDHoPar.reserve( 7) ; vdHoPar.reserve( 7) ; vnDHoPar.emplace_back( 1) ; vdHoPar.emplace_back( ptCen.x) ; vnDHoPar.emplace_back( 2) ; vdHoPar.emplace_back( ptCen.y) ; vnDHoPar.emplace_back( 3) ; vdHoPar.emplace_back( 0) ; vnDHoPar.emplace_back( 6) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 7) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 11) ; vdHoPar.emplace_back( GetSideHeight( nSide)) ; vnDHoPar.emplace_back( 12) ; vdHoPar.emplace_back( dHoDiam) ; STRVECTOR vsHoUAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHoUAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHoUAtt.emplace_back( sUAtt) ; } if ( ! AddDrill( nGroup + 2, 40, nSide, sDes, nProcId, Frame3d(), vnDHoPar, vdHoPar, vsHoUAtt)) return false ; // riferimenti reciproci int nAdjId = m_nProcId ; SetMainAdjId( nId, { nAdjId}) ; } m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddChamfer( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 : dPos) ; if ( dLen < EPS_SMALL) { dStart = 0 ; dEnd = GetSideLength( nSide) ; } else { dStart = max( dStart, 0.) ; dEnd = min( dEnd, GetSideLength( nSide)) ; } dLen = dEnd - dStart ; // eventuale lettura parametri Q e conseguente correzione dati int nWaves = 0 ; if ( m_bUseUAttr) { double dQ01 ; if ( GetUserParam( vsUAtt, "Q01", dQ01)) { nWaves = lround( dQ01 + 0.1) ; if ( nWaves < 2 || nWaves > 6) nWaves = 0 ; } } // creo gli smussi richiesti INTVECTOR vIds ; 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 ; // se normale if ( nWaves == 0) { // 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( STM_COMPACT_APPROX) ; // 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 SetParams( nId, vnDPar, vdPar, vsUAtt) ; // attributi utente SetUserAttributes( nId, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } // altrimenti ad onde else { // lunghezze dei tratti DBLVECTOR vLen ; GetWaveLengths( nWaves, dLen, vLen) ; DBLVECTOR vRed ; GetWaveReductions( nWaves, GetSideWidth( 1), vRed) ; if ( ( i % 2) == 0) { reverse( vLen.begin(), vLen.end()) ; reverse( vRed.begin(), vRed.end()) ; } // calcolo di ogni tratto double dRef = dStart ; for ( int j = 0 ; j < nWaves ; ++ j) { PtrOwner pArc( CreateCurveArc()) ; Point3d ptStart( dRef + vRed[j], 0, 0) ; Point3d ptMid( dRef + vLen[j]/2, dDepth/2, -dDepth/2) ; Point3d ptEnd( dRef + vLen[j] - vRed[j], 0, 0) ; if ( IsNull( pArc) || ! pArc->Set3P( ptStart, ptMid, ptEnd)) return false ; pArc->SetExtrusion( pArc->GetNormVersor()) ; dRef += vLen[j] ; // lo porto nel riferimento della faccia pArc->ToGlob( GetSideFrame( nRefSide)) ; // ricavo la spezzata che la approssima PolyLine PL ; if ( ! pArc->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL)) return false ; // creo la superficie di estrusione corrispondente PtrOwner pStm( CreateSurfTriMesh()) ; Vector3d vtExtr ; pArc->GetExtrusion( vtExtr) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, -vtExtr * 2 * dDepth)) return false ; // la centro sulla curva pStm->Translate( vtExtr * dDepth) ; // 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 string sMyDes = ToString( i) + "-" + ToString( j + 1) + "-" + sDes ; SetNameAndInfo( nId, nGroup, nProc, nSide, sMyDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // attributi utente SetUserAttributes( nId, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; // salvo Id vIds.emplace_back( nId) ; } } } // se non è stata inserita alcuna geometria if ( vIds.empty()) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // assegnazione geometria principale m_nProcId = vIds.front() ; vIds.erase( vIds.begin()) ; // eventuali riferimenti reciproci if ( ! vIds.empty()) SetMainAdjId( m_nProcId, vIds) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::GetWaveLengths( int nWaves, double dLen, DBLVECTOR& vLen) { // previste tra 2 e 6 onde if ( nWaves < 2 || nWaves > 6) return false ; vLen.resize( nWaves) ; switch ( nWaves) { case 2 : vLen[0] = dLen * 2 / 5 ; vLen[1] = dLen * 3 / 5 ; break ; case 3 : vLen[0] = dLen * 2 / 9 ; vLen[1] = dLen * 4 / 9 ; vLen[2] = dLen * 3 / 9 ; break ; case 4 : vLen[0] = dLen * 2 / 14 ; vLen[1] = dLen * 5 / 14 ; vLen[2] = dLen * 3 / 14 ; vLen[3] = dLen * 4 / 14 ; break ; case 5 : vLen[0] = dLen * 2 / 20 ; vLen[1] = dLen * 5 / 20 ; vLen[2] = dLen * 3 / 20 ; vLen[3] = dLen * 6 / 20 ; vLen[4] = dLen * 4 / 20 ; break ; case 6 : vLen[0] = dLen * 2 / 27 ; vLen[1] = dLen * 4 / 27 ; vLen[2] = dLen * 6 / 27 ; vLen[3] = dLen * 3 / 27 ; vLen[4] = dLen * 7 / 27 ; vLen[5] = dLen * 5 / 27 ; break ; } return true ; } //---------------------------------------------------------------------------- bool BtlGeom::GetWaveReductions( int nWaves, double dWidth, DBLVECTOR& vRed) { vRed.resize( nWaves) ; for ( int i = 0 ; i < nWaves ; ++ i) vRed[i] = dWidth * ( ( i % 2) == 0 ? 0.15 : 0.3) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLogHouseHL4( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 16) return false ; // sistemo i dati Point3d ptP( vdPar[0], 0, 0) ; // P01 double dWidth = Clamp( vdPar[1], 0., 50000.) ; // P03 if ( dWidth < EPS_SMALL) dWidth = GetSideHeight( nSide) ; int nType = lround( vdPar[2]) ; // P04 int nHole = lround( vdPar[3]) ; // P05 double dDepth1 = Clamp( vdPar[4], 0., 50000.) ; // P08 double dLength1 = Clamp( vdPar[5], 0., 50000.) ; // P09 double dDepth2 = Clamp( vdPar[6], 0., 50000.) ; // P10 double dLength2 = Clamp( vdPar[7], 0., 50000.) ; // P11 double dDepth3 = Clamp( vdPar[8], 0., 50000.) ; // P12 double dLength3 = Clamp( vdPar[9], 0., 50000.) ; // P13 double dDepth4 = Clamp( vdPar[10], 0., 50000.) ; // P14 double dLength4 = Clamp( vdPar[11], 0., 50000.) ; // P15 INTVECTOR vIds ; // se va fatto scasso sulla faccia di riferimento if ( dDepth1 > EPS_SMALL && dLength1 > EPS_SMALL) { // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( ! CreatePolygonInBox( ( ptP - vtN1 * dLength1 / 2), vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength1 / 2), -vtN1, nSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - dDepth1 * 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } // se va fatto scasso sulla faccia opposta a quella di riferimento if ( dDepth2 > EPS_SMALL && dLength2 > EPS_SMALL) { // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( ! CreatePolygonInBox( ( ptP - vtN1 * dLength2 / 2), vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength2 / 2), -vtN1, nSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - ( GetSideHeight( nSide) - dDepth2) * 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } // se va fatto scasso sulla faccia davanti a quella di riferimento if ( dDepth3 > EPS_SMALL && dLength3 > EPS_SMALL) { double dLenRef = ( dLength1 > EPS_SMALL ? dLength1 : dLength2) ; // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; double dPosStart = -dLength3 / 2 ; if ( nType == 1) dPosStart = -dLenRef / 2 ; else if ( nType == 2) dPosStart = dLenRef / 2 - dLength3 ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dPosStart), vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; double dPosEnd = dLength3 / 2 ; if ( nType == 1) dPosEnd = -dLenRef / 2 + dLength3 ; else if ( nType == 2) dPosEnd = dLenRef / 2 ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dPosEnd), -vtN1, nSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP + dDepth3 * Y_AX, -Y_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 ; // eventuale faccia di limitazione Polygon3d plyLimit ; if ( dWidth > EPS_SMALL && dWidth < GetSideHeight( nSide) - EPS_SMALL) { // creazione if ( ! CreatePolygonInBox( ptP - dWidth * Z_AX, Z_AX, nSide, plyLimit)) return false ; // trim con le altre facce if ( ! plyStart.Trim( plyLimit, false, true) || ! plyLimit.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyLimit, false, true) || ! plyLimit.Trim( plyEnd, false, false)) return false ; if ( ! plyBottom.Trim( plyLimit, false, true) || ! plyLimit.Trim( plyBottom, 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) ; DoSewing( pStm, plyLimit) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } // se va fatto scasso sulla faccia dietro a quella di riferimento if ( dDepth4 > EPS_SMALL && dLength4 > EPS_SMALL) { double dLenRef = ( dLength1 > EPS_SMALL ? dLength1 : dLength2) ; // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; double dPosStart = -dLength4 / 2 ; if ( nType == 1) dPosStart = dLenRef / 2 - dLength4 ; else if ( nType == 2) dPosStart = -dLenRef / 2 ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dPosStart), vtN1, nSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; double dPosEnd = dLength4 / 2 ; if ( nType == 1) dPosEnd = dLenRef / 2 ; else if ( nType == 2) dPosEnd = -dLenRef / 2 + dLength4 ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dPosEnd), -vtN1, nSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP + ( GetSideWidth( nSide) - dDepth4) * Y_AX, Y_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 ; // eventuale faccia di limitazione Polygon3d plyLimit ; if ( dWidth > EPS_SMALL && dWidth < GetSideHeight( nSide) - EPS_SMALL) { // creazione if ( ! CreatePolygonInBox( ptP - dWidth * Z_AX, Z_AX, nSide, plyLimit)) return false ; // trim con le altre facce if ( ! plyStart.Trim( plyLimit, false, true) || ! plyLimit.Trim( plyStart, false, false)) return false ; if ( ! plyEnd.Trim( plyLimit, false, true) || ! plyLimit.Trim( plyEnd, false, false)) return false ; if ( ! plyBottom.Trim( plyLimit, false, true) || ! plyLimit.Trim( plyBottom, 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) ; DoSewing( pStm, plyLimit) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } // se non è stata inserita alcuna geometria if ( vIds.empty()) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // aggiungo eventuale foro if ( nHole != 0) { INTVECTOR vnDHoPar ; DBLVECTOR vdHoPar ; vnDHoPar.reserve( 7) ; vdHoPar.reserve( 7) ; vnDHoPar.emplace_back( 1) ; vdHoPar.emplace_back( ptP.x) ; vnDHoPar.emplace_back( 2) ; vdHoPar.emplace_back( GetSideWidth( nSide) / 2) ; vnDHoPar.emplace_back( 3) ; vdHoPar.emplace_back( 0) ; vnDHoPar.emplace_back( 6) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 7) ; vdHoPar.emplace_back( 90) ; vnDHoPar.emplace_back( 11) ; vdHoPar.emplace_back( GetSideHeight( nSide)) ; vnDHoPar.emplace_back( 12) ; vdHoPar.emplace_back( 16) ; STRVECTOR vsHoUAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHoUAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHoUAtt.emplace_back( sUAtt) ; } vsHoUAtt.emplace_back( "\"DiamUser\":\"1\"") ; if ( ! AddDrill( nGroup, 40, nSide, sDes, nProcId, Frame3d(), vnDHoPar, vdHoPar, vsHoUAtt)) return false ; // salvo Id vIds.emplace_back( m_nProcId) ; } // assegnazione geometria principale m_nProcId = vIds.front() ; vIds.erase( vIds.begin()) ; // eventuali riferimenti reciproci if ( ! vIds.empty()) SetMainAdjId( m_nProcId, vIds) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddLogHouseFront( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 7) return false ; // sistemo i dati double dPos = vdPar[0] ; // P01 int nFlag = lround( vdPar[1]) ; // P04 double dAngle = Clamp( vdPar[2], 0.1, 179.9) ; // P06 double dDepth1 = Clamp( vdPar[3], -50000., 50000.) ; // P11 double dDepth2 = Clamp( vdPar[4], -50000., 50000.) ; // P12 double dDepth3 = Clamp( vdPar[5], -50000., 50000.) ; // P13 double dLength = Clamp( vdPar[6], 0., 50000.) ; // P15 // punto di riferimento Point3d ptP( dPos, 0, 0) ; // versore facce di testa Vector3d vtN1 = FromSpherical( 1, 90, -90 - dAngle) ; if ( nGroup == 3) vtN1.Mirror( X_AX) ; // faccia di testa Polygon3d plyStart ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyStart)) return false ; // faccia finale Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ptP - vtN1 * dLength, vtN1, nSide, plyEnd)) return false ; // faccia intermedia Vector3d vtV1 = - X_AX * dLength / vtN1.x ; Vector3d vtV2 = vtV1 ; if ( nGroup == 4) vtV2.Rotate( Z_AX, 180 - dAngle) ; else vtV2.Rotate( Z_AX, - ( 180 - dAngle)) ; vtV1 -= Z_AX * ( dDepth3 - dDepth1) ; vtV2 -= Z_AX * ( dDepth2 - dDepth1) ; Vector3d vtN2 = vtV1 ^ vtV2 ; vtN2.Normalize() ; if ( vtN2.z < 0) vtN2.Invert() ; Polygon3d plyMid ; if ( ! CreatePolygonInBox( ptP - Z_AX * dDepth1, vtN2, nSide, plyMid)) return false ; // creo la trimesh con la faccia di testa int nAuxId = GDB_ID_NULL ; PtrOwner pStmAux( CreateSurfTriMesh()) ; if ( IsNull( pStmAux)) return false ; if ( pStmAux->CreateByFlatContour( plyStart.GetPolyLine())) { // inserisco la superficie nel DB geometrico nAuxId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmAux)) ; if ( nAuxId == GDB_ID_NULL) return false ; } // trim tra le facce media e finale if ( ! plyEnd.Trim( plyMid, false, true) || ! plyMid.Trim( plyEnd, false, false)) return false ; // creo la trimesh per il trim dell'outline (arriva fino ai bordi della faccia del solido) PtrOwner pStmTrim( CreateSurfTriMesh()) ; if ( IsNull( pStmTrim)) return false ; DoSewing( pStmTrim, plyEnd) ; DoSewing( pStmTrim, plyMid) ; pStmTrim->DoCompacting( STM_COMPACT_APPROX) ; // trim con la faccia di testa if ( ! plyMid.Trim( plyStart, true, false)) return false ; // creo la trimesh con le facce intermedia e finale PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; DoSewing( pStm, plyEnd) ; DoSewing( pStm, plyMid) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // se richiesto, aggiungo la superficie simmetrica if ( nFlag == 1) { // copio la superficie principale int nSimId = m_pGDB->CopyGlob( nId, GDB_ID_NULL, m_nProcsId) ; if ( nSimId == GDB_ID_NULL) return false ; // eseguo la simmetria Plane3d plMirr = GetSidePlane( nSide) ; plMirr.Translate( - plMirr.GetVersN() * GetSideHeight( nSide) / 2) ; m_pGDB->Mirror( nSimId, plMirr.GetPoint(), plMirr.GetVersN()) ; // nome e info con tipo SetNameAndInfo( nSimId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nSimId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nSimId, {nAuxId}) ; // riferimenti reciproci SetMainAdjId( nId, { nSimId}) ; } m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddPocket( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 frMyRef( ptP) ; frMyRef.Rotate( frMyRef.Orig(), frMyRef.VersZ(), dAngle) ; frMyRef.Rotate( frMyRef.Orig(), frMyRef.VersY(), dIncl) ; frMyRef.Rotate( frMyRef.Orig(), frMyRef.VersX(), dSlope) ; frMyRef.ToGlob( frRef) ; ptP = frMyRef.Orig() ; // creo il poligono della faccia di fondo Vector3d vtN1 = frMyRef.VersZ() ; Polygon3d plyFace1 ; if ( ( nFlag & 16) == 0 && ! CreatePolygonInBox( ptP, vtN1, nSide, plyFace1)) return false ; // creo il poligono della faccia sinistra Vector3d vtN2 = frMyRef.VersX() ; vtN2.Rotate( frMyRef.VersZ(), dIntAng - 90) ; Polygon3d plyFace2 ; if ( ( nFlag & 1) == 0 && ! CreatePolygonInBox( ptP, vtN2, nSide, plyFace2)) return false ; // creo il poligono della faccia destra Polygon3d plyFace4 ; if ( ( nFlag & 2) == 0 && ! CreatePolygonInBox( ptP + vtN2 * dLen, - vtN2, nSide, plyFace4)) return false ; // creo il poligono della faccia davanti Vector3d vtN3 = frMyRef.VersY() ; Polygon3d plyFace3 ; if ( ( nFlag & 4) == 0 && ! CreatePolygonInBox( ptP, vtN3, nSide, plyFace3)) return false ; // creo il poligono della faccia dietro Polygon3d plyFace5 ; if ( ( nFlag & 8) == 0 && ! CreatePolygonInBox( ptP + vtN3 * dWidth, - vtN3, nSide, plyFace5)) return false ; // verifico tra loro le facce if ( ! VerifyPolygonWithPolygons( plyFace1, plyFace2, plyFace3, plyFace4, plyFace5, false)) plyFace1.Clear() ; if ( ! VerifyPolygonWithPolygons( plyFace2, plyFace3, plyFace1, plyFace5, false)) plyFace2.Clear() ; if ( ! VerifyPolygonWithPolygons( plyFace3, plyFace2, plyFace1, plyFace4, false)) plyFace3.Clear() ; if ( ! VerifyPolygonWithPolygons( plyFace4, plyFace3, plyFace1, plyFace5, false)) plyFace4.Clear() ; if ( ! VerifyPolygonWithPolygons( plyFace5, plyFace2, plyFace1, plyFace4, false)) plyFace5.Clear() ; // 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( STM_COMPACT_APPROX) ; // 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) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDrill( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 = AngleNearAngle( vdPar[3], 180.) ; // P06 double dAngVert = Clamp( abs( vdPar[4]), 1., 179.) ; // P07 double dOrthoDepth = ( vdPar[5] < 0.5 ? GetSideHeight( nSide) : vdPar[5]) ; // P11 double dRad = vdPar[6] / 2 ; // P12 // calcolo affondamento double dDepth = dOrthoDepth / sin( dAngVert * DEGTORAD) ; // verifica del raggio if ( dRad < 0.5) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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) ; } } // porto i dati in globale Frame3d frMyRef = frRef * GetSideFrame( nSide) ; ptP.ToGlob( frMyRef) ; vtN.ToGlob( frMyRef) ; // determino i punti iniziale e finale Point3d ptStart = ptP ; Point3d ptEnd = ptP - vtN * dDepth ; // limito i punti, tenendo conto del raggio if ( ! TrimSegmentWithBox( ptStart, ptEnd, dRad)) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // verifico la profondità dDepth = ( ptStart - ptEnd) * vtN ; if ( dDepth < 0.5) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // creo la circonferenza PtrOwner pArc( CreateCurveArc()) ; if ( IsNull( pArc)) return false ; // assegno i dati if ( ! pArc->Set( ptStart, vtN, dRad)) return false ; pArc->SetExtrusion( vtN) ; pArc->SetThickness( - dDepth) ; // verifico se inizio su faccia (o fuori) int nStartFace = 0 ; double dTanStart = 0 ; double dMaxCosStart = COS_ALMOST_PERP ; for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_RIGHT ; ++ i) { Plane3d plSide = GetSidePlane( i) ; double dCosStart = vtN * plSide.GetVersN() ; if ( DistPointPlane( ptStart, plSide) > - TOL_OPEN_DRILL && dCosStart > dMaxCosStart) { nStartFace = i ; double dSinStart = sqrt( max( 0., 1 - dCosStart * dCosStart)) ; dTanStart = dSinStart / dCosStart ; dMaxCosStart = dCosStart ; } } if ( ptStart.x > GetSideLength( nSide) - TOL_DRILL_H_T && vtN * X_AX > COS_ALMOST_PERP) nStartFace = BTL_SIDE_RIGHT ; else if ( ptStart.x < TOL_DRILL_H_T && vtN * -X_AX > COS_ALMOST_PERP) nStartFace = BTL_SIDE_LEFT ; double dStartAgg = (( nStartFace == 0 || dTanStart < EPS_SMALL) ? 0 : dRad * dTanStart + LEN_EXTRUS_AGG) ; // verifico se fine su faccia (o fuori) int nEndFace = 0 ; double dTanEnd = 0 ; double dMaxCosEnd = COS_ALMOST_PERP ; for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_RIGHT ; ++ i) { Plane3d plSide = GetSidePlane( i) ; double dCosEnd = -vtN * plSide.GetVersN() ; if ( DistPointPlane( ptEnd, plSide) > - TOL_OPEN_DRILL && dCosEnd > dMaxCosEnd) { nEndFace = i ; double dSinEnd = sqrt( max( 0., 1 - dCosEnd * dCosEnd)) ; dTanEnd = dSinEnd / dCosEnd ; dMaxCosEnd = dCosEnd ; } } if ( ptEnd.x > GetSideLength( nSide) - TOL_DRILL_H_T && vtN * -X_AX > COS_ALMOST_PERP) nEndFace = BTL_SIDE_RIGHT ; else if ( ptEnd.x < TOL_DRILL_H_T && vtN * X_AX > COS_ALMOST_PERP) nEndFace = BTL_SIDE_LEFT ; double dEndAgg = (( nEndFace == 0 || dTanEnd < EPS_SMALL) ? 0 : dRad * dTanEnd + 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_SPECIAL, PL) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( vtN) ; // creo la superficie trimesh laterale del foro PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, - vtN * ( dDepth + dStartAgg + dEndAgg))) return false ; pStm->Translate( vtN * dStartAgg) ; // se chiuso, creo la superficie trimesh di fondo del foro if ( nEndFace == 0) { PtrOwner pStmBot( CreateSurfTriMesh()) ; if ( IsNull( pStmBot) || ! pStmBot->CreateByPointCurve( ptStart, PL)) return false ; pStmBot->Translate( - vtN * dDepth) ; pStm->DoSewing( *pStmBot) ; } pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // flag per apertura foro su inizio/fine SetDrillEnds( nId, nStartFace, nEndFace) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddTenon( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 12) return false ; // flag per house bool bHouse = ( nProc == 52) ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; // P01, P02 int nFlag = lround( vdPar[2]) ; // P04 double dAngle = Clamp( vdPar[4], 0.1, 179.9) ; // P06 double dInclination = Clamp( vdPar[5], 0.1, 179.9) ; // P07 double dRot = Clamp( vdPar[6], 0.1, 179.9) ; // P08 double dFillet = vdPar[7] ; // P10 double dTenH = vdPar[8] ; // P11 double dTenW = vdPar[9] ; // P12 double dTenM1 = ( abs( vdPar[10]) < 100 * EPS_SMALL ? 0 : vdPar[10]) ; // P14 double dTenM2 = ( abs( vdPar[11]) < 100 * EPS_SMALL ? 0 : vdPar[11]) ; // P15 // eventuale lettura parametri Q e conseguente correzione dati if ( m_bUseUAttr) { double dQ02 ; if ( GetUserParam( vsUAtt, "Q02", dQ02)) dTenH -= dQ02 ; double dQ03 ; if ( GetUserParam( vsUAtt, "Q03", dQ03)) dTenW -= dQ03 ; double dQ04 ; if ( GetUserParam( vsUAtt, "Q04", dQ04)) { dTenM1 += dQ04 / 2 ; dTenM2 += dQ04 / 2 ; } } // 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, 0)) return false ; if ( plyCut.GetSideCount() < 3 || dTenH < EPS_SMALL || dTenW < EPS_SMALL) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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 ; if ( dTenL > m_vtDim.x + m_vtDim.y + m_vtDim.z) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Wrong Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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 { 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_SPECIAL, 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 ; if ( pReg->GetAuxSurf() != nullptr) { pStm.Set( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStm)) return false ; } // se non è House, creo la superficie trimesh di testa del tenone PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ( ! bHouse && ! pStmCap->CreateByPointCurve( ptCen, PL))) return false ; pStmCap->Translate( frTen.VersZ() * dTenH) ; // creo la superficie trimesh laterale del tenone PtrOwner pStmTen( CreateSurfTriMesh()) ; if ( IsNull( pStmTen) || ! pStmTen->CreateByExtrusion( PL, frTen.VersZ() * dTenH)) return false ; // eseguo trim con le facce della trave (base già nella trave) TrimSurfTmWithBox( pStmCap) ; TrimSurfTmWithBox( pStmTen) ; // unisco le facce secondo l'ordine : base, sopra, altre if ( IsNull( pStm)) pStm.Set( pStmCap) ; else pStm->DoSewing( *pStmCap) ; pStm->DoSewing( *pStmTen) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddMortise( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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.) ; if ( abs( dStartZ) < MORTISE_DISPL_MIN) dStartZ = 0 ; 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( frRef) ; 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 == 0 || nFlag == 1 || nFlag == 3) { 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 { double dRad = 0.5 * min( dMortW, dMortL) ; 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_SPECIAL, 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)) + -dStartZ / vtN3.z ; 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() ; // eseguo trim delle due superfici con le facce della trave TrimSurfTmWithBox( pStm) ; TrimSurfTmWithBox( pStmMort) ; // unisco le due superfici pStm->DoSewing( *pStmMort) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // se superficie risultante vuota if ( pStm->GetTriangleCount() == 0) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // eseguo trim della curva con le facce della trave PtrOwner pNewCrvMort( TrimFlatCurveWithBoxEx( pCrvMort->Clone(), 0)) ; // inserisco la curva nel DB geometrico int nMId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, ( IsNull( pNewCrvMort) ? Release( pCrvMort) : Release( pNewCrvMort))) ; if ( nMId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nMId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddMortiseFront( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 ? 0.0 : vdPar[9]) ; double dMortM2 = ( abs( vdPar[10]) < 10 * EPS_SMALL ? 0.0 : 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 == 0 || nFlag == 1 || nFlag == 3) { 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 { double dRad = 0.5 * min( dMortW, dMortL) ; 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_SPECIAL, PL) || ! pCompo->FromPolyLine( PL)) return false ; pCompo->SetExtrusion( frMort.VersZ()) ; // definisco la superficie di taglio PtrOwner pStmCut ; // 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 della mortasa SurfFlatRegionByContours SfrMrt ; SfrMrt.AddCurve( pCompo->Clone()) ; PtrOwner pMrt( SfrMrt.GetSurf()) ; if ( IsNull( pMrt)) return false ; // sottraggo la regione della mortasa da quella esterna if ( ! pReg->Subtract( *pMrt)) return false ; // ne deduco la superficie trimesh if ( pReg->GetAuxSurf() != nullptr) { pStmCut.Set( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStmCut)) return false ; } } // 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) ; // creo la superficie trimesh della mortasa PtrOwner pStmMrt( CreateSurfTriMesh()) ; if ( IsNull( pStmMrt) || ! pStmMrt->CreateByExtrusion( PL, - frMort.VersZ() * dMortD)) return false ; // eseguo trim delle due superfici con le facce della trave TrimSurfTmWithBox( pStmCap) ; TrimSurfTmWithBox( pStmMrt) ; // unisco le facce secondo l'ordine : fondo, taglio, altre PtrOwner pStm( Release( pStmCap)) ; if ( ! IsNull( pStmCut)) pStm->DoSewing( *pStmCut) ; pStm->DoSewing( *pStmMrt) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // se superficie risultante vuota if ( pStm->GetTriangleCount() == 0) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // eseguo trim della curva con le facce della trave pCrvTen->Translate( - frMort.VersZ() * dMortD) ; PtrOwner pNewCrvTen( TrimFlatCurveWithBoxEx( pCrvTen->Clone(), 0)) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, ( IsNull( pNewCrvTen) ? Release( pCrvTen) : Release( pNewCrvTen))) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDovetailTenon( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 12) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; // P01, P02 int nFlag = lround( vdPar[2]) ; // P04 double dAngle = Clamp( vdPar[3], 0.1, 179.9) ; // P06 double dInclination = Clamp( vdPar[4], 0.1, 179.9) ; // P07 double dRot = Clamp( vdPar[5], 0.1, 179.9) ; // P08 double dTenW = vdPar[6] ; // P09 double dTenA = Clamp( vdPar[7], 0., 30.) ; // P10 double dTenH = vdPar[8] ; // P11 double dFillet = vdPar[9] / 2 ; // P12 double dDtMillDefRad = DTMILL_DEF_RAD - dTenH * tan( DOVETAIL_DEF_ANG * DEGTORAD) ; if ( dFillet < dDtMillDefRad && dTenW + 2 * max( dFillet, 0.) >= 2 * dDtMillDefRad) { dTenW -= 2 * ( dDtMillDefRad - max( dFillet, 0.)) ; dFillet = dDtMillDefRad ; } else if ( dFillet < 0) dFillet = 0 ; double dTenM1 = ( abs( vdPar[10]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[10]) ; // P14 double dTenM2 = ( abs( vdPar[11]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[11]) ; // P15 // eventuale lettura parametri Q e conseguente correzione dati if ( m_bUseUAttr) { double dQ03 ; if ( GetUserParam( vsUAtt, "Q03", dQ03)) dTenH -= dQ03 ; double dQ04 ; if ( GetUserParam( vsUAtt, "Q04", dQ04)) dFillet -= dQ04 / 2 ; double dQ05 ; if ( GetUserParam( vsUAtt, "Q05", dQ05)) dTenM2 += dQ05 ; } // calcolo la normale alla faccia del taglio Vector3d vtN = FromSpherical( 1, 180 + dInclination, dAngle - 90) ; if ( nGroup == 1) vtN.Mirror( X_AX) ; // eventuale micro aggiustamento della posizione per evitare problemi con piccoli triangoli AdjustPointForPlaneNearBoxVertex( ptP, vtN, nSide) ; // creo il poligono di taglio Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, vtN, nSide, plyCut)) return false ; if ( plyCut.GetSideCount() == 0 || dTenH < EPS_SMALL) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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 ; if ( dTenL > m_vtDim.x + m_vtDim.y + m_vtDim.z) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Wrong Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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_SPECIAL, 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_SPECIAL, 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 ; if ( pReg->GetAuxSurf() != nullptr) { pStm.Set( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStm)) return false ; } // Creo la superficie trimesh del tenone PtrOwner pStmTen( CreateSurfTriMesh()) ; if ( IsNull( pStmTen) || ! pStmTen->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR)) return false ; // 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, ISurfTriMesh::RLT_ISOPAR)) return false ; // Creo la superficie trimesh di testa del tenone PL2.Close() ; PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL2)) return false ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStmCap) ; TrimSurfTmWithBox( pStmTen) ; TrimSurfTmWithBox( pStmTen2) ; // Unisco le superfici nell'ordine opportuno if ( IsNull( pStm)) pStm.Set( pStmCap) ; else pStm->DoSewing( *pStmCap) ; pStm->DoSewing( *pStmTen) ; pStm->DoSewing( *pStmTen2) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDovetailMortise( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 14) return false ; // sistemo i dati double dStartX = vdPar[0] ; // P01 double dStartY = vdPar[1] ; // P02 double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; // P03 if ( abs( dStartZ) < MORTISE_DISPL_MIN) dStartZ = 0 ; int nFlag = lround( vdPar[3]) ; // P04 int nPock = lround( vdPar[4]) ; // P05 double dAngle = Clamp( vdPar[5], -180.0, 180.0) ; // P06 double dMortW = vdPar[7] ; // P09 double dMortA = Clamp( vdPar[8], 0., 30.) ; // P10 double dMortD = vdPar[9] ; // P11 double dFillet = vdPar[10] / 2 ; // P12 double dDtMillDefRad = DTMILL_DEF_RAD - dMortD * tan( DOVETAIL_DEF_ANG * DEGTORAD) ; if ( dFillet < dDtMillDefRad && dMortW + 2 * max( dFillet, 0.) >= 2 * dDtMillDefRad) { dMortW -= 2 * ( dDtMillDefRad - max( dFillet, 0.)) ; dFillet = dDtMillDefRad ; } else if ( dFillet < 0) dFillet = 0 ; double dStrutAng = Clamp( vdPar[6], 0.1, 179.9) ; // P07 double dMortM1 = vdPar[12] ; // P14 double dMortM2 = vdPar[13] ; // P15 if ( nFlag == 1) dMortM2 = - dDtMillDefRad - DTMORT_EXTRA_LEN ; double dMortL = Clamp( vdPar[11] / sin( dStrutAng * DEGTORAD) - dMortM1 - dMortM2, 1., 99999.) ; // P13 // punto di riferimento Point3d ptP( dStartX, dStartY, dStartZ) ; ptP.ToGlob( frRef) ; // calcolo riferimento della faccia sopra Frame3d frMort = frRef ; frMort.Rotate( frMort.Orig(), frMort.VersZ(), ( 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 ; double dExtraLen ; if ( nPock == 0) { dExtraLen = GetSideWidth( nSide) ; dX4 = dX3 + ( dExtraLen - dY3) * sin( dMortA * DEGTORAD) ; dY4 = dExtraLen ; } else { dExtraLen = MAX_DTMORT_POCKET ; if ( dMortA > EPS_ANG_SMALL) dExtraLen = Clamp( 0.6225 * dOffs / sin( dMortA * DEGTORAD), MIN_DTMORT_POCKET, 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) ; // se senza tasca, allungamento per arrivare sicuramente al bordo if ( nPock == 0) { double dAddLenMax = max( abs( GetSideLength( nSide) - dStartX), abs( dStartX)) ; double dAddLen = dAddLenMax ; if ( abs( dAngle) > EPS_ANG_SMALL && abs( dAngle) < 180 - EPS_ANG_SMALL) dAddLen = min( dAddLenMax, GetSideWidth( nSide) / sin( abs( dAngle) * DEGTORAD)) ; pCrvTop->ExtendStartByLen( dAddLen) ; pCrvTop->ExtendEndByLen( dAddLen) ; } // Creo il contorno basso della mortasa PtrOwner pCrvMort( pCrvTop->Clone()) ; if ( IsNull( pCrvMort)) return false ; pCrvMort->SimpleOffset( dOffs, ICurve::OFF_EXTEND) ; pCrvMort->Translate( -Z_AX * 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) ; } // altrimenti con tasca, sistemo il contorno alto else { delete pCrvTop->RemoveFirstOrLastCurve( true) ; delete pCrvTop->RemoveFirstOrLastCurve( false) ; pCrvTop->AddLine( Point3d( dX4 + dOffs, dY3, 0), true) ; pCrvTop->AddLine( Point3d( dX4 + dOffs, dY4, 0), true) ; pCrvTop->AddLine( Point3d( -dX4 - dOffs, dY3, 0), false) ; pCrvTop->AddLine( Point3d( -dX4 - dOffs, dY4, 0), false) ; } // sistemo per il riferimento pCrvTop->ToGlob( frMort) ; pCrvMort->ToGlob( frMort) ; // Approssimo le curve con spezzate PolyLine PL2 ; if ( ! pCrvTop->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL2)) return false ; PolyLine PL1 ; if ( ! pCrvMort->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL1)) return false ; // Se con tasca PtrOwner pCrvPock ; if ( nPock != 0) { // accorcio la curva di base (tolgo quasi tutta la tasca) pCrvMort->TrimStartAtLen( dExtraLen - 2.) ; double dLen ; pCrvMort->GetLength( dLen) ; pCrvMort->TrimEndAtLen( dLen - dExtraLen + 2.) ; // creo la curva di contorno della tasca pCrvPock.Set( CreateCurveComposite()) ; if ( IsNull( pCrvPock)) return false ; pCrvPock->AddPoint( Point3d( -dX4 - dOffs, dY4, 0)) ; pCrvPock->AddLine( Point3d( -dX4 - dOffs, dY3, 0)) ; pCrvPock->AddLine( Point3d( dX4 + dOffs, dY3, 0)) ; pCrvPock->AddLine( Point3d( dX4 + dOffs, dY4, 0)) ; pCrvPock->Close() ; pCrvPock->SetExtrusion( Z_AX) ; pCrvPock->Translate( -Z_AX * dMortD) ; pCrvPock->ToGlob( frMort) ; } // Creo la superficie trimesh laterale della mortasa PtrOwner pStmSide( CreateSurfTriMesh()) ; if ( IsNull( pStmSide) || ! pStmSide->CreateByTwoCurves( PL2, PL1, ( nPock == 0 ? ISurfTriMesh::RLT_ISOPAR : ISurfTriMesh::RLT_MINDIST))) 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, ISurfTriMesh::RLT_ISOPAR)) return false ; pStmMrt->Invert() ; // creo la superficie trimesh di fondo della mortasa PL1.Close() ; PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL1)) return false ; // eseguo trim con le facce della trave TrimSurfTmWithBox( pStmSide) ; TrimSurfTmWithBox( pStmMrt) ; TrimSurfTmWithBox( pStmCap) ; // Unisco le varie superfici PtrOwner pStm( Release( pStmCap)) ; pStm->DoSewing( *pStmSide) ; pStm->DoSewing( *pStmMrt) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // se superficie risultante vuota if ( pStm->GetTriangleCount() == 0) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // 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 ; // inserisco eventuale curva della tasca nel DB geometrico int nPId = GDB_ID_NULL ; if ( ! IsNull( pCrvPock)) { // verifico se la curva ha parti significative entro il solido della trave PtrOwner pTestPock( TrimFlatCurveWithBoxEx( pCrvPock->Clone())) ; Plane3d plPlane ; double dArea ; if ( IsNull( pTestPock) || ! pTestPock->GetArea( plPlane, dArea) || dArea < MIN_DTMORT_AREA) { nPock = 0 ; } else { // eseguo trim allargato con solido trave PtrOwner pNewPock( TrimFlatCurveWithBoxEx( Release( pCrvPock), DTMORT_OUT_CRV_TOL)) ; // inserisco nel DB nPId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pNewPock)) ; if ( nPId == GDB_ID_NULL) return false ; } } // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametri DBLVECTOR vdMyPar = vdPar ; vdMyPar[4] = nPock ; SetParams( nId, vnDPar, vdMyPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nMId, nPId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDtMortiseFront( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 14) return false ; // sistemo i dati double dStartX = vdPar[0] ; // P01 double dStartY = vdPar[1] ; // P02 double dStartZ = - Clamp( vdPar[2], 0., 50000.) ; // P03 if ( abs( dStartZ) < MORTISE_DISPL_MIN) dStartZ = 0 ; int nFlag = lround( vdPar[3]) ; // P04 int nPock = lround( vdPar[4]) ; // P05 double dAngle = Clamp( vdPar[5], 0.1, 179.9) ; // P06 double dInclination = Clamp( vdPar[6], 0.1, 179.9) ; // P07 double dRot = Clamp( vdPar[7], 0.1, 179.9) ; // P08 double dMortW = vdPar[8] ; // P09 double dMortA = Clamp( vdPar[9], 0., 30.) ; // P10 double dMortD = vdPar[10] ; // P11 double dFillet = vdPar[11] / 2 ; // P12 double dDtMillDefRad = DTMILL_DEF_RAD - dMortD * tan( DOVETAIL_DEF_ANG * DEGTORAD) ; if ( dFillet < dDtMillDefRad && dMortW + 2 * dFillet >= 2 * dDtMillDefRad) { dMortW -= 2 * ( dDtMillDefRad - dFillet) ; dFillet = dDtMillDefRad ; } else if ( dFillet < 0) dFillet = 0 ; double dMortM1 = ( abs( vdPar[12]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[12]) ; // P14 double dMortM2 = ( abs( vdPar[13]) < 10 * EPS_SMALL ? 10 * EPS_SMALL : vdPar[13]) ; // P15 if ( nFlag == 1) dMortM2 = - dDtMillDefRad - DTMORT_EXTRA_LEN ; // punto di riferimento Point3d ptP( dStartX, dStartY, dStartZ) ; // 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 ; if ( dMortL < 10 * EPS_SMALL) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // 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 ; double dExtraLen ; if ( nPock == 0) { dExtraLen = GetSideWidth( nSide) ; dX4 = dX3 + ( dExtraLen - dY3) * sin( dMortA * DEGTORAD) ; dY4 = dExtraLen ; } else { dExtraLen = MAX_DTMORT_POCKET ; if ( dMortA > EPS_ANG_SMALL) dExtraLen = min( 0.6225 * 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) ; // Creo il contorno basso della mortasa PtrOwner pCrvMort( pCrvTop->Clone()) ; if ( IsNull( pCrvMort)) return false ; pCrvMort->SimpleOffset( dOffs, ICurve::OFF_EXTEND) ; pCrvMort->Translate( -Z_AX * 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) ; } // altrimenti con tasca, sistemo il contorno alto else { delete pCrvTop->RemoveFirstOrLastCurve( true) ; delete pCrvTop->RemoveFirstOrLastCurve( false) ; pCrvTop->AddLine( Point3d( dX4 + dOffs, dY3, 0), true) ; pCrvTop->AddLine( Point3d( dX4 + dOffs, dY4, 0), true) ; pCrvTop->AddLine( Point3d( -dX4 - dOffs, dY3, 0), false) ; pCrvTop->AddLine( Point3d( -dX4 - dOffs, dY4, 0), false) ; } // sistemo per il riferimento pCrvTop->ToGlob( frMort) ; pCrvMort->ToGlob( frMort) ; // Se con tasca PtrOwner pCrvPock ; if ( nPock != 0) { // accorcio la curva di base (tolgo quasi tutta la tasca) pCrvMort->TrimStartAtLen( dExtraLen - 2.) ; double dLen ; pCrvMort->GetLength( dLen) ; pCrvMort->TrimEndAtLen( dLen - dExtraLen + 2.) ; // creo la curva di contorno della tasca pCrvPock.Set( CreateCurveComposite()) ; if ( IsNull( pCrvPock)) return false ; pCrvPock->AddPoint( Point3d( -dX4 - dOffs, dY4, 0)) ; pCrvPock->AddLine( Point3d( -dX4 - dOffs, dY3, 0)) ; pCrvPock->AddLine( Point3d( dX4 + dOffs, dY3, 0)) ; pCrvPock->AddLine( Point3d( dX4 + dOffs, dY4, 0)) ; pCrvPock->Close() ; pCrvPock->SetExtrusion( Z_AX) ; pCrvPock->Translate( -Z_AX * dMortD) ; pCrvPock->ToGlob( frMort) ; } // Approssimo le curve con spezzate PolyLine PL2 ; if ( ! pCrvTop->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL2)) return false ; PolyLine PL1 ; if ( ! pCrvMort->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL1)) return false ; // Creo il contorno superiore per la regione PtrOwner pCompo( CreateCurveComposite()) ; if ( ! 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())) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } SurfFlatRegionByContours SfrExt ; SfrExt.AddCurve( Release( pExt)) ; PtrOwner pReg( SfrExt.GetSurf()) ; if ( IsNull( pReg)) return false ; // Creo la regione della mortasa SurfFlatRegionByContours SfrMort ; SfrMort.AddCurve( Release( pCompo)) ; 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 pStmCut ; if ( pReg->GetAuxSurf()) { pStmCut.Set( pReg->GetAuxSurf()->Clone()) ; if ( IsNull( pStmCut)) return false ; } // Creo la superficie trimesh della mortasa PtrOwner pStmTen( CreateSurfTriMesh()) ; if ( IsNull( pStmTen) || ! pStmTen->CreateByTwoCurves( PL2, PL1, ( nPock == 0 ? ISurfTriMesh::RLT_ISOPAR : ISurfTriMesh::RLT_MINDIST))) 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, ISurfTriMesh::RLT_ISOPAR)) return false ; pStmMrt->Invert() ; // creo la superficie trimesh di fondo della mortasa PL1.Close() ; PtrOwner pStmCap( CreateSurfTriMesh()) ; if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL1)) return false ; // eseguo trim con le facce della trave (taglio già nella trave) TrimSurfTmWithBox( pStmTen) ; TrimSurfTmWithBox( pStmMrt) ; TrimSurfTmWithBox( pStmCap) ; // unisco le facce secondo l'ordine : fondo, taglio, altre PtrOwner pStm( Release( pStmCap)) ; if ( ! IsNull( pStmCut)) pStm->DoSewing( *pStmCut) ; pStm->DoSewing( *pStmTen) ; pStm->DoSewing( *pStmMrt) ; pStm->DoCompacting( STM_COMPACT_APPROX) ; // se superficie risultante vuota if ( pStm->GetTriangleCount() == 0) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // inserisco la superficie trimesh nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // 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 ; // inserisco eventuale curva della tasca nel DB geometrico int nPId = GDB_ID_NULL ; if ( ! IsNull( pCrvPock)) { // verifico se la curva ha parti significative entro il solido della trave PtrOwner pTestPock( TrimFlatCurveWithBoxEx( pCrvPock->Clone())) ; Plane3d plPlane ; double dArea ; if ( IsNull( pTestPock) || ! pTestPock->GetArea( plPlane, dArea) || dArea < MIN_DTMORT_AREA) { nPock = 0 ; } else { // eseguo trim allargato con solido trave PtrOwner pNewPock( TrimFlatCurveWithBoxEx( Release( pCrvPock), DTMORT_OUT_CRV_TOL)) ; // inserisco nel DB nPId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pNewPock)) ; if ( nPId == GDB_ID_NULL) return false ; } } // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri DBLVECTOR vdMyPar = vdPar ; vdMyPar[4] = nPock ; SetParams( nId, vnDPar, vdMyPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, { nTId, nPId}) ; m_nProcId = 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, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 8) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; // P01, P02 int nFlag = lround( vdPar[2]) ; // P04 double dAng = Clamp( vdPar[3], 1., 180.) ; // P06 double dIntAng = Clamp( vdPar[4], 0., 179.) ; // P07 double dWidth = Clamp( vdPar[5], 0., 50000.) ; // P11 double dQuadH = Clamp( vdPar[6], 0., 50000.) ; // P12 if ( abs( dQuadH) < EPS_SMALL) dQuadH = GetSideWidth( nSide) - ptP.y ; double dTextH = Clamp( vdPar[7], 0., 50000.) ; // P13 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 if ( nFlag > 0 && ! IsEmptyOrSpaces( sPar)) { // assegno il testo string sText = sPar ; // assegno la direzione Vector3d vtDir = X_AX ; bool bHoriz = true ; bool bPlus = true ; if ( ( nFlag & 128) != 0) { vtDir = X_AX ; bHoriz = true ; bPlus = true ; } else if ( ( nFlag & 256) != 0) { vtDir = -Y_AX ; bHoriz = false ; bPlus = false ; } else if ( ( nFlag & 512) != 0) { vtDir = -X_AX ; bHoriz = true ; bPlus = false ; } else if ( ( nFlag & 1024) != 0) { vtDir = Y_AX ; bHoriz = false ; bPlus = true ; } // assegno la posizione di inserimento const double TEXT_OFFY = 5 ; Point3d ptPos( vdPar[0], 0, 0) ; int nInsPos = ETXT_IPMC ; if ( ( nFlag & 2) != 0) { ptPos += TEXT_OFFY * Y_AX ; if ( bHoriz) ptPos += dTextH / 2 * Y_AX ; else { if ( bPlus) nInsPos = ETXT_IPML ; else nInsPos = ETXT_IPMR ; } } else if ( ( nFlag & 4) != 0) { ptPos += GetSideWidth( nSide) / 2 * Y_AX ; } else if ( ( nFlag & 8) != 0) { ptPos += ( GetSideWidth( nSide) - TEXT_OFFY) * Y_AX ; if ( bHoriz) ptPos += - dTextH / 2 * Y_AX ; else { if ( bPlus) nInsPos = ETXT_IPMR ; else nInsPos = ETXT_IPML ; } } else if ( ( nFlag & 4096) != 0) { ptPos = ptP ; if ( bHoriz) ptPos += - dTextH / 2 * Y_AX ; else { if ( bPlus) nInsPos = ETXT_IPMR ; else nInsPos = ETXT_IPML ; } } else if ( ( nFlag & 8192) != 0) { ptPos = ptP ; } else if ( ( nFlag & 16384) != 0) { ptPos = ptP ; if ( bHoriz) ptPos += dTextH / 2 * Y_AX ; else { if ( bPlus) nInsPos = ETXT_IPML ; else nInsPos = ETXT_IPMR ; } } if ( ( nFlag & 16) != 0) { if ( bHoriz) { if ( bPlus) nInsPos = ETXT_IPMR ; else nInsPos = ETXT_IPML ; } else ptPos += -dTextH / 2 * X_AX ; } else if ( ( nFlag & 32) != 0) ptPos += dWidth / 2 * X_AX ; else if ( ( nFlag & 64) != 0) { ptPos += dWidth * X_AX ; if ( bHoriz) { if ( bPlus) nInsPos = ETXT_IPML ; else nInsPos = ETXT_IPMR ; } else ptPos += dTextH / 2 * X_AX ; } // creo il testo PtrOwner pText( CreateExtText()) ; if ( IsNull( pText)) return false ; // assegno i dati if ( ! pText->Set( ptPos, Z_AX, vtDir, sText, "", 100, false, dTextH, 1, 0, nInsPos)) return false ; // porto il testo nel piano della faccia 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 ; // imposto se elemento principale o ausiliario if ( nMainId == GDB_ID_NULL) nMainId = nId ; else vAuxId.emplace_back( nId) ; } // 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, vsUAtt) ; 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 int nDO ; bool bEnabled = ( ! m_pGDB->GetInfo( nMainId, IKEY_DO, nDO) || nDO != 0) ; m_pGDB->SetMaterial( nMainId, ( bEnabled ? m_MarkCol : m_ProcsOffCol)) ; for ( auto nId : vAuxId) m_pGDB->SetMaterial( nId, ( bEnabled ? m_MarkCol : m_ProcsOffCol)) ; } // altrimenti emetto segnalazione else { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; nMainId = m_nProcId ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) } m_nProcId = nMainId ; 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, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 8) return false ; // se stringa vuota o solo spazi, creo feature vuota if ( IsEmptyOrSpaces( sPar)) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], 0) ; // P01, P02 Vector3d vtD = FromPolar( 1, vdPar[2]) ; // P06 double dH = vdPar[7] ; // P13 int nInsPos ; switch ( lround( vdPar[3])) { // P09 case 0 : switch ( lround( vdPar[4])) { // P10 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) // P12 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, vsUAtt) ; string sKey = IKEY_PAR + ToString( nSPar, 2) ; m_pGDB->SetInfo( nId, sKey, sPar) ; // colore per linee di marcatura e testi int nDO ; bool bEnabled = ( ! m_pGDB->GetInfo( nId, IKEY_DO, nDO) || nDO != 0) ; m_pGDB->SetMaterial( nId, ( bEnabled ? m_MarkCol : m_ProcsOffCol)) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddSimpleScarf( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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) + dDepthOpp) ; // 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( STM_COMPACT_APPROX) ; // se non è stata inserita alcuna geometria if ( pStm->GetTriangleCount() == 0) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // calcolo la direttrice di questa superficie rigata Vector3d vtExtr = GetSideVersN( nSide) ^ vtN ; PtrOwner pCrv( GetDirectrixOfRuledSurf( pStm, vtExtr)) ; if ( IsNull( pCrv)) return false ; // imposto estrusione e spessore pCrv->SetExtrusion( vtExtr) ; pCrv->SetThickness( -GetSideWidth( nSide)) ; // 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( pCrv)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiungo eventuali fori if ( dHoDiam1 > 10 * EPS_SMALL) { INTVECTOR vIds ; // primo foro double dHo1Dist = ( dHoDiam2 < 10 * EPS_SMALL ? dLength / 2 : dLength / 3) ; double dHo1PosX = dStartX + ( nGroup == 2 ? dHo1Dist : -dHo1Dist) ; INTVECTOR vnDHo1Par ; DBLVECTOR vdHo1Par ; vnDHo1Par.reserve( 7) ; vdHo1Par.reserve( 7) ; vnDHo1Par.emplace_back( 1) ; vdHo1Par.emplace_back( dHo1PosX) ; vnDHo1Par.emplace_back( 2) ; vdHo1Par.emplace_back( GetSideWidth( nSide) / 2) ; vnDHo1Par.emplace_back( 3) ; vdHo1Par.emplace_back( 0) ; vnDHo1Par.emplace_back( 6) ; vdHo1Par.emplace_back( 90) ; vnDHo1Par.emplace_back( 7) ; vdHo1Par.emplace_back( 90) ; vnDHo1Par.emplace_back( 11) ; vdHo1Par.emplace_back( GetSideHeight( nSide)) ; vnDHo1Par.emplace_back( 12) ; vdHo1Par.emplace_back( dHoDiam1) ; STRVECTOR vsHo1UAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHo1UAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHo1UAtt.emplace_back( sUAtt) ; } if ( ! AddDrill( nGroup + 2, 40, nSide, sDes, nProcId, Frame3d(), vnDHo1Par, vdHo1Par, vsHo1UAtt)) return false ; vIds.emplace_back( m_nProcId) ; // secondo foro if ( dHoDiam2 > 10 * EPS_SMALL) { double dHo2Dist = 2 * dLength / 3 ; double dHo2PosX = dStartX + ( nGroup == 2 ? dHo2Dist : -dHo2Dist) ; INTVECTOR vnDHo2Par ; DBLVECTOR vdHo2Par ; vnDHo2Par.reserve( 7) ; vdHo2Par.reserve( 7) ; vnDHo2Par.emplace_back( 1) ; vdHo2Par.emplace_back( dHo2PosX) ; vnDHo2Par.emplace_back( 2) ; vdHo2Par.emplace_back( GetSideWidth( nSide) / 2) ; vnDHo2Par.emplace_back( 3) ; vdHo2Par.emplace_back( 0) ; vnDHo2Par.emplace_back( 6) ; vdHo2Par.emplace_back( 90) ; vnDHo2Par.emplace_back( 7) ; vdHo2Par.emplace_back( 90) ; vnDHo2Par.emplace_back( 11) ; vdHo2Par.emplace_back( GetSideHeight( nSide)) ; vnDHo2Par.emplace_back( 12) ; vdHo2Par.emplace_back( dHoDiam2) ; STRVECTOR vsHo2UAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHo2UAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHo2UAtt.emplace_back( sUAtt) ; } if ( ! AddDrill( nGroup + 2, 40, nSide, sDes, nProcId, Frame3d(), vnDHo2Par, vdHo2Par, vsHo2UAtt)) return false ; vIds.emplace_back( m_nProcId) ; } // riferimenti reciproci SetMainAdjId( nId, vIds) ; } m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddScarfJoint( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 = ptQ - Z_AX * dLapDepth / vtV2.z + 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 ; // sistemo la curva PtrOwner pCrv( CreateCurveComposite()) ; if ( IsNull( pCrv) || ! pCrv->FromPolyLine( PL)) return false ; if ( nGroup == 2) pCrv->Invert() ; pCrv->SetExtrusion( -frSide.VersY()) ; pCrv->SetThickness( -GetSideWidth( nSide)) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrv)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; // aggiungo eventuali fori if ( dHoDiam1 > 10 * EPS_SMALL) { INTVECTOR vIds ; // primo foro double dHo1Dist = ( dHoDiam2 < 10 * EPS_SMALL ? dLength / 2 : dLength / 3) ; double dHo1PosX = dStartX + ( nGroup == 2 ? dHo1Dist : -dHo1Dist) ; INTVECTOR vnDHo1Par ; DBLVECTOR vdHo1Par ; vnDHo1Par.reserve( 7) ; vdHo1Par.reserve( 7) ; vnDHo1Par.emplace_back( 1) ; vdHo1Par.emplace_back( dHo1PosX) ; vnDHo1Par.emplace_back( 2) ; vdHo1Par.emplace_back( GetSideWidth( nSide) / 2) ; vnDHo1Par.emplace_back( 3) ; vdHo1Par.emplace_back( 0) ; vnDHo1Par.emplace_back( 6) ; vdHo1Par.emplace_back( 90) ; vnDHo1Par.emplace_back( 7) ; vdHo1Par.emplace_back( 90) ; vnDHo1Par.emplace_back( 11) ; vdHo1Par.emplace_back( GetSideHeight( nSide)) ; vnDHo1Par.emplace_back( 12) ; vdHo1Par.emplace_back( dHoDiam1) ; STRVECTOR vsHo1UAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHo1UAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHo1UAtt.emplace_back( sUAtt) ; } if ( ! AddDrill( nGroup + 2, 40, nSide, sDes, nProcId, Frame3d(), vnDHo1Par, vdHo1Par, vsHo1UAtt)) return false ; vIds.emplace_back( m_nProcId) ; // secondo foro if ( dHoDiam2 > 10 * EPS_SMALL) { double dHo2Dist = 2 * dLength / 3 ; double dHo2PosX = dStartX + ( nGroup == 2 ? dHo2Dist : -dHo2Dist) ; INTVECTOR vnDHo2Par ; DBLVECTOR vdHo2Par ; vnDHo2Par.reserve( 7) ; vdHo2Par.reserve( 7) ; vnDHo2Par.emplace_back( 1) ; vdHo2Par.emplace_back( dHo2PosX) ; vnDHo2Par.emplace_back( 2) ; vdHo2Par.emplace_back( GetSideWidth( nSide) / 2) ; vnDHo2Par.emplace_back( 3) ; vdHo2Par.emplace_back( 0) ; vnDHo2Par.emplace_back( 6) ; vdHo2Par.emplace_back( 90) ; vnDHo2Par.emplace_back( 7) ; vdHo2Par.emplace_back( 90) ; vnDHo2Par.emplace_back( 11) ; vdHo2Par.emplace_back( GetSideHeight( nSide)) ; vnDHo2Par.emplace_back( 12) ; vdHo2Par.emplace_back( dHoDiam2) ; STRVECTOR vsHo2UAtt ; for ( const auto& sUAtt : vsUAtt) { if ( sUAtt.find( "\"Q") != 0) vsHo2UAtt.emplace_back( sUAtt) ; if ( sUAtt.find( "\"TASKID") != 0) vsHo2UAtt.emplace_back( sUAtt) ; } if ( ! AddDrill( nGroup + 2, 40, nSide, sDes, nProcId, Frame3d(), vnDHo2Par, vdHo2Par, vsHo2UAtt)) return false ; vIds.emplace_back( m_nProcId) ; } // riferimenti reciproci SetMainAdjId( nId, vIds) ; } m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddStepJoint( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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( 1, ptT) ; PL.AddUPoint( 2, ptS) ; PL.AddUPoint( 3, 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 ; // sistemo la curva PtrOwner pCrv( CreateCurveComposite()) ; if ( IsNull( pCrv) || ! pCrv->FromPolyLine( PL)) return false ; if ( nGroup == 1) pCrv->Invert() ; pCrv->SetExtrusion( -frSide.VersY()) ; pCrv->SetThickness( -GetSideWidth( nSide)) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrv)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddStepJointNotch( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 7) return false ; // sistemo i dati double dStartX = vdPar[0] ; // P01 double dStartY = max( vdPar[1], 0.) ; // 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 dWidth = min( dWidth, GetSideWidth( nSide) - dStartY) ; 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 > 100 * 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, ISurfTriMesh::RLT_ISOPAR)) return false ; if ( nGroup == 4) pSfr->Invert() ; // la unisco alla superficie principale if ( ! pStm->DoSewing( *pSfr)) return false ; } // definisco ed aggiungo eventuale faccia posteriore if ( dStartY + dWidth < GetSideWidth( nSide) - 100 * 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, ISurfTriMesh::RLT_ISOPAR)) return false ; // la inverto e la traslo if ( nGroup == 3) pSfr->Invert() ; pSfr->Translate( frSide.VersY() * dWidth) ; // la unisco alla superficie principale if ( ! pStm->DoSewing( *pSfr)) return false ; } pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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 ; // sistemo la curva PtrOwner pCrv( CreateCurveComposite()) ; if ( IsNull( pCrv) || ! pCrv->FromPolyLine( PL)) return false ; if ( nGroup == 3) pCrv->Invert() ; if ( dStartY < 0) pCrv->Translate( - dStartY * frSide.VersY()) ; pCrv->SetExtrusion( frSide.VersY()) ; double dThick = min( dWidth + min( 0., dStartY), GetSideWidth( nSide)- max( 0., dStartY)) ; pCrv->SetThickness( dThick) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrv)) ; if ( nTId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddPlaning( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 4) return false ; // sistemo i dati Point3d ptP( vdPar[0], 0, 0) ; // P01 int nType = Clamp( lround( vdPar[1]), 1, 15) ; // P04 double dDepth = Clamp( vdPar[2], 0., 50.) ; // P11 double dLength = Clamp( vdPar[3], -99999., 99999.) ; // P12 // lato di riferimento fisso int nRefSide = 1 ; INTVECTOR vIds ; // se va fatto scasso sulla faccia di riferimento if ( ( nType & 1) != 0) { // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( ! CreatePolygonInBox( ptP, vtN1, nRefSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength), -vtN1, nRefSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - dDepth * Z_AX, Z_AX, nRefSide, 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( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico if ( ! pStm->IsEmpty()) { 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } } // se va fatto scasso sulla faccia opposta a quella di riferimento if ( ( nType & 4) != 0) { // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( ! CreatePolygonInBox( ptP, vtN1, nRefSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength), -vtN1, nRefSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP - ( GetSideHeight( nRefSide) - dDepth) * Z_AX, -Z_AX, nRefSide, 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( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico if ( ! pStm->IsEmpty()) { 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } } // se va fatto scasso sulla faccia davanti a quella di riferimento if ( ( nType & 2) != 0) { // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( ! CreatePolygonInBox( ptP, vtN1, nRefSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength), -vtN1, nRefSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP + dDepth * Y_AX, -Y_AX, nRefSide, 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( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico if ( ! pStm->IsEmpty()) { 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } } // se va fatto scasso sulla faccia dietro a quella di riferimento if ( ( nType & 8) != 0) { // faccia di inizio Polygon3d plyStart ; Vector3d vtN1 = X_AX ; if ( ! CreatePolygonInBox( ptP, vtN1, nRefSide, plyStart)) return false ; // faccia di fine Polygon3d plyEnd ; if ( ! CreatePolygonInBox( ( ptP + vtN1 * dLength), -vtN1, nRefSide, plyEnd)) return false ; // faccia di fondo Polygon3d plyBottom ; if ( ! CreatePolygonInBox( ptP + ( GetSideWidth( nRefSide) - dDepth) * Y_AX, Y_AX, nRefSide, 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( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico if ( ! pStm->IsEmpty()) { 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, vsUAtt) ; // salvo Id vIds.emplace_back( nId) ; } } // se non è stata inserita alcuna geometria if ( vIds.empty()) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // assegnazione geometria principale m_nProcId = vIds.front() ; vIds.erase( vIds.begin()) ; // eventuali riferimenti reciproci if ( ! vIds.empty()) SetMainAdjId( m_nProcId, vIds) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProfileFront( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 7) return false ; // sistemo i dati double dP01 = vdPar[0] ; // P01 double dP03 = Clamp( vdPar[1], -1000., 1000.) ; // P03 double dP06 = Clamp( vdPar[2], 0., 180.) ; // P06 double dP07 = Clamp( vdPar[3], 0., 180.) ; // P07 double dP08 = Clamp( vdPar[4], -180., 180.) ; // P08 double dP11 = Clamp( vdPar[5], -1000., 1000.) ; // P11 double dP12 = Clamp( vdPar[6], -1000., 1000.) ; // P12 // faccia di riferimento int nRefSide = ( ( nSide - 1) >= BTL_SIDE_FRONT ? ( nSide - 1) : BTL_SIDE_TOP) ; // calcolo i punti double dPos = (( nGroup == 3) ? GetSideLength( nRefSide) - dP01 : dP01) ; Point3d ptC1( dPos + abs( dP11), dP03 + abs( dP11), 0) ; Vector3d vtDirI1 = - X_AX ; vtDirI1.Rotate( Z_AX, dP08) ; Point3d ptP2 = ptC1 + vtDirI1 * abs( dP11) ; Point3d ptP1 ; if ( ! TrimRayWithFaceContour( ptP2, vtDirI1, nRefSide, ptP1)) ptP1 = ptP2 ; Vector3d vtDirF1 = vtDirI1 ; vtDirF1.Rotate( Z_AX, dP06) ; Point3d ptP3 = ptC1 + vtDirF1 * abs( dP11) ; Vector3d vtDirI2 = - vtDirF1 ; Point3d ptC2 = ptP3 - vtDirI2 * abs( dP12) ; Vector3d vtDirF2 = vtDirI2 ; vtDirF2.Rotate( Z_AX, -dP07) ; Point3d ptP4 = ptC2 + vtDirF2 * abs( dP12) ; Point3d ptP5 ; if ( abs( dP12) < EPS_SMALL || dP07 < EPS_ANG_SMALL) { if ( ! TrimRayWithFaceContour( ptP4, vtDirF1, nRefSide, ptP5)) ptP5 = ptP4 ; } else { Vector3d vtTgF2 = vtDirF2 ; vtTgF2.Rotate( Z_AX, -90) ; if ( ! TrimRayWithFaceContour( ptP4, vtTgF2, nRefSide, ptP5)) ptP5 = ptP4 ; } double dBulge1 = ( abs( dP11) > EPS_SMALL ? tan( 0.25 * dP06 * DEGTORAD) : 0) ; double dBulge2 = ( abs( dP12) > EPS_SMALL ? tan( 0.25 * -dP07 * DEGTORAD) : 0) ; // costruisco la curva del profilo PolyArc PA ; PA.AddUPoint( 0, ptP1, 0) ; PA.AddUPoint( 1, ptP2, 0) ; PA.ModifyLastBulge( (( dP11 < 0) ? -dBulge1 : dBulge1)) ; PA.AddUPoint( 2, ptP3, 0) ; PA.ModifyLastBulge( (( dP12 < 0) ? -dBulge2 : dBulge2)) ; PA.AddUPoint( 3, ptP4, 0) ; PA.AddUPoint( 4, ptP5, 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( Point3d( 0.5 * GetSideLength( nRefSide), 0, 0), X_AX) ; // sistemo per riferimento faccia Frame3d frRef ; frRef = GetSideFrame( nRefSide) ; pCrvCo->ToGlob( frRef) ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvCo) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, 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()) ; } // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProfileHeadCoCo( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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.) ; double dP00 = (( nGroup == 3) ? GetSideLength( nSide) : 0) ; double dOffs = (( nGroup == 3) ? 2 * ( dP00 - dP01) : 0) ; Point3d ptP1( dP00, dP14 + dP11 + dP12, 0) ; Point3d ptP2( dP01 + dOffs + dP13, dP14 + dP11 + dP12, 0) ; Point3d ptP3( dP01 + dOffs + dP13, dP14 + dP11, 0) ; Point3d ptP4( dP01 + dOffs + dP13 + dP11, dP14, 0) ; Point3d ptP5( dP01 + dOffs + dP13 + dP11 + dP15, dP14, 0) ; Point3d ptP6( dP01 + dOffs + dP13 + dP11 + dP15, 0, 0) ; // costruisco la curva del profilo PolyArc PA ; 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) ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvCo) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, 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()) ; } // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProfileHeadCambered( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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.1 ; for ( int i = 1 ; i <= 10 ; ++ i) { double dCurrMax = -INFINITO ; for ( double dU = 0.1 ; dU <= 0.4 + EPS_ZERO ; dU += 0.05) { Point3d ptP ; if ( pCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP)) dCurrMax = max( dCurrMax, ptP.y) ; } double dCurrMin = INFINITO ; for ( double dU = 0.6 ; dU <= 0.9 + EPS_ZERO ; dU += 0.05) { Point3d ptP ; if ( pCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP)) dCurrMin = min( dCurrMin, ptP.y) ; } double dDeltaMax = dMax - dCurrMax ; double dDeltaMin = dMin - dCurrMin ; 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) ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvCo) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, 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) ; // riordino le facce (sempre dall'estremo verso il centro trave) int nFacCnt = pStm->GetFacetCount() ; for ( int i = 0 ; i < nFacCnt - 1 ; ++ i) { Point3d ptCenI ; Vector3d vtNI ; if ( pStm->GetFacetCenter( i, ptCenI, vtNI)) { for ( int j = i + 1 ; j < nFacCnt ; ++ j) { Point3d ptCenJ ; Vector3d vtNJ ; if ( pStm->GetFacetCenter( j, ptCenJ, vtNJ)) { if ( ( nGroup == 4 && ptCenJ.x < ptCenI.x) || ( nGroup == 3 && ptCenJ.x > ptCenI.x)) { pStm->SwapFacets( i, j) ; ptCenI = ptCenJ ; vtNI = vtNJ ; } } } } } // 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()) ; } // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddProfileHead( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 16) return false ; // assegno i dati double dP01 = vdPar[0] ; // P01 int nFlag = lround( vdPar[1]) ; // P04 double dP09 = Clamp( vdPar[2], 0., 1000.) ; // P09 double dP10 = Clamp( vdPar[3], 0., 1000.) ; // P10 double dP11 = Clamp( vdPar[4], 0., 1000.) ; // P11 double dP12 = Clamp( vdPar[5], 0., 1000.) ; // P12 double dP13 = Clamp( vdPar[6], 0., 1000.) ; // P13 double dP14 = Clamp( vdPar[7], 0., 1000.) ; // P14 double dP15 = Clamp( vdPar[8], 0., 1000.) ; // P15 double dP16 = Clamp( vdPar[9], 0., 1000.) ; // P16 double dP17 = Clamp( vdPar[10], 0., 1000.) ; // P17 double dP18 = Clamp( vdPar[11], 0., 1000.) ; // P18 double dP19 = Clamp( vdPar[12], 0., 1000.) ; // P19 double dP20 = Clamp( vdPar[13], 0., 1000.) ; // P20 double dP21 = Clamp( vdPar[14], 0., 1000.) ; // P21 double dP22 = Clamp( vdPar[15], 0., 1000.) ; // P22 // sistemo i dati double dBulgeArc1 = 0 ; if ( abs( dP12) > EPS_SMALL && abs( dP13) < EPS_SMALL && abs( dP14) < EPS_SMALL) { dP13 = dP12 ; dBulgeArc1 = BULGE_90D ; } else if ( abs( dP12) > EPS_SMALL && abs( dP13) > EPS_SMALL) dBulgeArc1 = 2 * dP14 / sqrt( dP12 * dP12 + dP13 * dP13) ; double dBulgeArc2 = 0 ; if ( abs( dP18) > EPS_SMALL && abs( dP19) < EPS_SMALL && abs( dP20) < EPS_SMALL) { dP19 = dP18 ; dBulgeArc2 = BULGE_90D ; } else if ( abs( dP18) > EPS_SMALL && abs( dP19) > EPS_SMALL) dBulgeArc2 = 2 * dP20 / sqrt( dP18 * dP18 + dP19 * dP19) ; // calcolo i punti Point3d ptP1( dP01, dP22 + dP19 + dP16 + dP13 + dP10, 0) ; Point3d ptP2( dP01 + dP09, dP22 + dP19 + dP16 + dP13 + dP10, 0) ; Point3d ptP3( dP01 + dP09, dP22 + dP19 + dP16 + dP13, 0) ; Point3d ptP4( dP01 + dP09 + dP11, dP22 + dP19 + dP16 + dP13, 0) ; Point3d ptP5( dP01 + dP09 + dP11 + dP12, dP22 + dP19 + dP16, 0) ; Point3d ptP6( dP01 + dP09 + dP11 + dP12 + dP15, dP22 + dP19 + dP16, 0) ; Point3d ptP7( dP01 + dP09 + dP11 + dP12 + dP15, dP22 + dP19, 0) ; Point3d ptP8( dP01 + dP09 + dP11 + dP12 + dP15 + dP17, dP22 + dP19, 0) ; Point3d ptP9( dP01 + dP09 + dP11 + dP12 + dP15 + dP17 + dP18, dP22, 0) ; Point3d ptPA( dP01 + dP09 + dP11 + dP12 + dP15 + dP17 + dP18 + dP21, dP22, 0) ; Point3d ptPB( dP01 + dP09 + dP11 + dP12 + dP15 + dP17 + dP18 + dP21, 0, 0) ; // costruisco la curva del profilo PolyArc PA ; PA.AddUPoint( 0, ptP1, 0) ; PA.AddUPoint( 0, ptP2, 0) ; PA.AddUPoint( 0, ptP3, 0) ; PA.AddUPoint( 0, ptP4, 0) ; PA.ModifyLastBulge( (( nFlag == 0 || nFlag == 2) ? -dBulgeArc1 : dBulgeArc1)) ; PA.AddUPoint( 0, ptP5, 0) ; PA.AddUPoint( 0, ptP6, 0) ; PA.AddUPoint( 0, ptP7, 0) ; PA.AddUPoint( 0, ptP8, 0) ; PA.ModifyLastBulge( (( nFlag == 0 || nFlag == 1) ? -dBulgeArc2 : dBulgeArc2)) ; PA.AddUPoint( 0, ptP9, 0) ; PA.AddUPoint( 0, ptPA, 0) ; PA.AddUPoint( 0, ptPB, 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) ; // eseguo trim della curva con le facce della trave TrimFlatCurveWithBox( pCrvCo) ; // creo la superficie di estrusione PolyLine PL ; pCrvCo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, 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()) ; } // 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddRoundArch( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // 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 false ; 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_SPECIAL, 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 ; // eseguo trim 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, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId}) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddTriangleCut( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 9) return false ; // sistemo i dati Point3d ptP( vdPar[0], vdPar[1], -vdPar[2]) ; // P01, P02, P03 Vector3d vtN1( vdPar[3], vdPar[4], vdPar[5]) ; // P10, P11, P12 Vector3d vtN2( vdPar[6], vdPar[7], vdPar[8]) ; // P13, P14, P15 // creo il primo poligono di taglio Polygon3d plyCut1 ; if ( ! vtN1.Normalize() || ! CreatePolygonInBox( ptP, vtN1, nSide, plyCut1)) return false ; // creo il secondo poligono di taglio Polygon3d plyCut2 ; if ( ! vtN2.Normalize() || ! CreatePolygonInBox( ptP, vtN2, nSide, plyCut2)) return false ; // trimmo tra loro le due facce if ( ! plyCut1.Trim( plyCut2, false, true) || ! plyCut2.Trim( plyCut1, false, 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( STM_COMPACT_APPROX) ; // 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, vsUAtt) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddTyroleanDovetail( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 15) return false ; // sistemo i dati double dPos = Clamp( vdPar[0], -99999., 99999.) ; // P01 double dInside = Clamp( vdPar[1], 0., 50000.) ; // P02 double dDepth = Clamp( vdPar[2], -50000., 50000.) ; // P03 int nInsPos = lround( vdPar[3]) ; // P04 double dRebMit = Clamp( vdPar[4], -1., 50000.) ; // P05 double dAngle = Clamp( vdPar[5], 0.1, 179.9) ; // P06 double dSlope = Clamp( vdPar[8], 0., 45.) ; // P09 double dHeight = Clamp( vdPar[9], 0., 50000.) ; // P11 double dLength = Clamp( vdPar[13], 0., 50000.) ; // P15 int nFlag = lround( vdPar[14]) ; // P16 // punto di riferimento Point3d ptP( dPos, 0, -dDepth) ; // faccia frontale Vector3d vtN1 = FromSpherical( 1, 90, 90 - dAngle) ; Vector3d vtTg = vtN1 ; vtTg.Rotate( Z_AX, 0, 1) ; if ( nGroup == 1 || nGroup == 3) { vtN1.Mirror( X_AX) ; vtTg.Mirror( X_AX) ; } Polygon3d plyFront ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyFront)) return false ; // faccia opposta Polygon3d plyOppo ; if ( ! CreatePolygonInBox( ptP + vtN1 * dLength, -vtN1, nSide, plyOppo)) return false ; // dati per facce sopra e sotto double dSinSlope = sin( dSlope * DEGTORAD) ; double dTanAngHalf = tan( ( nInsPos == 0 ? ( 180 - dAngle) : dAngle) / 2 * DEGTORAD) ; double dSpostX = dLength / vtN1.x ; double dSpostTg = ( nInsPos == 0 ? dInside : GetSideWidth( nSide) - dInside) / vtTg.y ; // se di estremità aggiungo faccia di taglio int nAuxId = GDB_ID_NULL ; if ( nGroup == 1 || nGroup == 2) { // come la faccia frontale ma invertita Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, -vtN1, nSide, plyCut)) return false ; // creo la trimesh con questa faccia PtrOwner pStmCut( CreateSurfTriMesh()) ; if ( IsNull( pStmCut)) return false ; if ( pStmCut->CreateByFlatContour( plyCut.GetPolyLine())) { // inserisco la superficie nel DB geometrico nAuxId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmCut)) ; if ( nAuxId == GDB_ID_NULL) return false ; } } INTVECTOR vIds ; // se prevista parte sopra, la inserisco if ( nFlag == 0 || nFlag == 1) { // copio le facce frontale e opposta Polygon3d plyFront1 ; if ( nGroup == 3 || nGroup == 4) plyFront1 = plyFront ; Polygon3d plyOppo1 = plyOppo ; // faccia di fondo double dNy = dSinSlope ; double dNx = dSinSlope / dTanAngHalf ; Vector3d vtN2( dNx, dNy, sqrt( 1 - dNx * dNx - dNy * dNy)) ; if ( nGroup == 1 || nGroup == 3) vtN2.Mirror( X_AX) ; if ( nInsPos != 0) vtN2.Mirror( Y_AX) ; Point3d ptQ = ptP + X_AX * dSpostX + Z_AX * dHeight + vtTg * dSpostTg ; Polygon3d plyBott1 ; if ( ! CreatePolygonInBox( ptQ, vtN2, nSide, plyBott1)) return false ; // taglio tra loro le tre facce if ( ! plyFront1.Trim( plyBott1, false, true) || ! plyBott1.Trim( plyFront1, false, false)) return false ; if ( ! plyOppo1.Trim( plyBott1, false, true) || ! plyBott1.Trim( plyOppo1, false, false)) return false ; // creo la trimesh con queste facce PtrOwner pStmUp( CreateSurfTriMesh()) ; if ( IsNull( pStmUp)) return false ; if ( ! DoSewing( pStmUp, plyFront1) || ! DoSewing( pStmUp, plyBott1) || ! DoSewing( pStmUp, plyOppo1)) return false ; pStmUp->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmUp)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // se presenti, aggiungo identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // salvo Id vIds.emplace_back( nId) ; } // se prevista parte sotto, la inserisco if ( nFlag == 0 || nFlag == 2) { // copio le facce frontale e opposta Polygon3d plyFront2 ; if ( nGroup == 3 || nGroup == 4) plyFront2 = plyFront ; Polygon3d plyOppo2 = plyOppo ; // faccia di sopra double dNy = dSinSlope ; double dNx = dSinSlope / dTanAngHalf ; Vector3d vtN2( dNx, dNy, -sqrt( 1 - dNx * dNx - dNy * dNy)) ; if ( nGroup == 1 || nGroup == 3) vtN2.Mirror( X_AX) ; if ( nInsPos != 0) vtN2.Mirror( Y_AX) ; Point3d ptQ = ptP + X_AX * dSpostX - Z_AX * dHeight + vtTg * dSpostTg ; Polygon3d plyBott2 ; if ( ! CreatePolygonInBox( ptQ, vtN2, nSide, plyBott2)) return false ; // taglio tra loro le tre facce if ( ! plyFront2.Trim( plyBott2, false, true) || ! plyBott2.Trim( plyFront2, false, false)) return false ; if ( ! plyOppo2.Trim( plyBott2, false, true) || ! plyBott2.Trim( plyOppo2, false, false)) return false ; // creo la trimesh con queste facce PtrOwner pStmDw( CreateSurfTriMesh()) ; if ( IsNull( pStmDw)) return false ; if ( ! DoSewing( pStmDw, plyFront2) || ! DoSewing( pStmDw, plyBott2) || ! DoSewing( pStmDw, plyOppo2)) return false ; pStmDw->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmDw)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // se presenti, aggiungo identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // salvo Id vIds.emplace_back( nId) ; } // eventuale rientro if ( dInside > EPS_SMALL) { // punto di riferimento Point3d ptQ = ptP + X_AX * dSpostX + vtTg * dSpostTg ; // faccia lunga Polygon3d plyLong ; if ( ! CreatePolygonInBox( ptQ, ( nInsPos == 0 ? -Y_AX : Y_AX), nSide, plyLong)) return false ; // faccia di contenimento Vector3d vtN3 = -vtN1 ; if ( dRebMit < 0) { vtN3 = -vtN1 + ( nInsPos == 0 ? -Y_AX : Y_AX) ; vtN3.Normalize() ; } Polygon3d plyShort ; if ( ! CreatePolygonInBox( ptQ + vtN1 * max( dRebMit, 0.), vtN3, nSide, plyShort)) return false ; // eventuale altra faccia di contenimento Polygon3d plyOther ; if ( nGroup == 3 || nGroup == 4) { if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyOther)) return false ; } // taglio tra loro le tre facce if ( ! plyLong.Trim( plyShort, false, true) || ! plyShort.Trim( plyLong, false, false)) return false ; if ( ! plyLong.Trim( plyOther, false, true) || ! plyOther.Trim( plyLong, false, false)) return false ; // creo la trimesh con queste facce PtrOwner pStmSd( CreateSurfTriMesh()) ; if ( IsNull( pStmSd)) return false ; if ( ! DoSewing( pStmSd, plyLong) || ! DoSewing( pStmSd, plyShort) || ! DoSewing( pStmSd, plyOther)) return false ; pStmSd->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmSd)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // se presenti, aggiungo identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // salvo Id vIds.emplace_back( nId) ; } // se non è stata inserita alcuna geometria if ( vIds.empty()) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // assegnazione geometria principale m_nProcId = vIds.front() ; vIds.erase( vIds.begin()) ; // eventuali riferimenti reciproci if ( ! vIds.empty()) SetMainAdjId( m_nProcId, vIds) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDovetail( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 11) return false ; // sistemo i dati double dPos = Clamp( vdPar[0], -99999., 99999.) ; // P01 double dInside = Clamp( vdPar[1], 0., 50000.) ; // P02 double dDepth = Clamp( vdPar[2], -50000., 50000.) ; // P03 int nInsPos = lround( vdPar[3]) ; // P04 double dRebMit = Clamp( vdPar[4], -1., 50000.) ; // P05 double dSlope = Clamp( vdPar[5], 0., 45.) ; // P09 double dDepth1 = Clamp( vdPar[6], 0., 50000.) ; // P11 double dDepth2 = Clamp( vdPar[7], 0., 50000.) ; // P12 int nType = lround( vdPar[8]) ; // P14 double dLength = Clamp( vdPar[9], 0., 50000.) ; // P15 int nFlag = lround( vdPar[10]) ; // P16 // punto di riferimento Point3d ptP( dPos, 0, -dDepth) ; // facce trasversali Vector3d vtN1 = ( ( nGroup == 2 || nGroup == 4) ? X_AX : -X_AX) ; Polygon3d plyFront ; if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyFront)) return false ; Polygon3d plyOppo ; if ( ! CreatePolygonInBox( ptP + vtN1 * dLength, -vtN1, nSide, plyOppo)) return false ; // dati per altre facce Vector3d vtN2 = FromSpherical( 1, dSlope, ( nInsPos == 0 ? 90: -90)) ; Vector3d vtN3 = FromSpherical( 1, 90 - dSlope, ( nInsPos == 0 ? -90: 90)) ; Vector3d vtN4 = FromSpherical( 1, 180 - dSlope, ( ( nGroup == 2 || nGroup == 4) ? 0: 180)) ; Vector3d vtN5 = FromSpherical( 1, 90 + dSlope, ( ( nGroup == 2 || nGroup == 4) ? 180: 0)) ; double dSpostY = ( nInsPos == 0 ? dInside : GetSideWidth( nSide) - dInside) ; // se di estremità aggiungo faccia di taglio int nAuxId = GDB_ID_NULL ; if ( nGroup == 1 || nGroup == 2) { // come la faccia frontale ma invertita Polygon3d plyCut ; if ( ! CreatePolygonInBox( ptP, -vtN1, nSide, plyCut)) return false ; // creo la trimesh con questa faccia PtrOwner pStmCut( CreateSurfTriMesh()) ; if ( IsNull( pStmCut)) return false ; if ( pStmCut->CreateByFlatContour( plyCut.GetPolyLine())) { // inserisco la superficie nel DB geometrico nAuxId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmCut)) ; if ( nAuxId == GDB_ID_NULL) return false ; } } INTVECTOR vIds ; // se prevista parte sopra, la inserisco if ( nFlag == 0 || nFlag == 1) { // copio le facce frontale e opposta Polygon3d plyFront1 ; if ( nGroup == 3 || nGroup == 4) plyFront1 = plyFront ; Polygon3d plyOppo1 = plyOppo ; // altre facce Point3d ptQ = ptP + vtN1 * dLength + Y_AX * dSpostY + Z_AX * dDepth1 ; Polygon3d plyBott1 ; if ( ! CreatePolygonInBox( ptQ, vtN2, nSide, plyBott1)) return false ; Polygon3d plyBott1b ; if ( nType == 0) { Point3d ptR = ptP + vtN1 * dLength + Y_AX * dSpostY ; if ( ! CreatePolygonInBox( ptR, vtN3, nSide, plyBott1b)) return false ; Polygon3d plyFront1b = plyFront1 ; Polygon3d plyOppo1b = plyOppo1 ; // taglio tra loro le facce if ( ! plyFront1.Trim( plyBott1, false, true) || ! plyBott1.Trim( plyFront1, false, false)) return false ; if ( ! plyOppo1.Trim( plyBott1, false, true) || ! plyBott1.Trim( plyOppo1, false, false)) return false ; if ( ! plyBott1.Trim( plyBott1b, true, true) || ! plyBott1b.Trim( plyBott1, true, false)) return false ; if ( ! plyFront1b.Trim( plyBott1, true, true) || ! plyOppo1b.Trim( plyBott1, true, true)) return false ; if ( ! plyFront1b.Trim( plyBott1b, false, true) || ! plyBott1b.Trim( plyFront1b, false, false)) return false ; if ( ! plyOppo1b.Trim( plyBott1b, false, true) || ! plyBott1b.Trim( plyOppo1b, false, false)) return false ; // unisco le due parti delle facce fronte e opposta if ( ! plyFront1.Add( plyFront1b) || ! plyOppo1.Add( plyOppo1b)) return false ; } else { // taglio tra loro le tre facce if ( ! plyFront1.Trim( plyBott1, false, true) || ! plyBott1.Trim( plyFront1, false, false)) return false ; if ( ! plyOppo1.Trim( plyBott1, false, true) || ! plyBott1.Trim( plyOppo1, false, false)) return false ; } // creo la trimesh con queste facce PtrOwner pStmUp( CreateSurfTriMesh()) ; if ( IsNull( pStmUp)) return false ; if ( ! DoSewing( pStmUp, plyFront1) || ! DoSewing( pStmUp, plyBott1) || ! DoSewing( pStmUp, plyBott1b) || ! DoSewing( pStmUp, plyOppo1)) return false ; pStmUp->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmUp)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // se presenti, aggiungo identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // salvo Id vIds.emplace_back( nId) ; } // se prevista parte sotto, la inserisco if ( nFlag == 0 || nFlag == 2) { // copio le facce frontale e opposta Polygon3d plyFront2 ; if ( nGroup == 3 || nGroup == 4) plyFront2 = plyFront ; Polygon3d plyOppo2 ; if ( nType == 0) { Point3d ptQ = ptP + vtN1 * dLength + Y_AX * dSpostY + Z_AX * ( dDepth - GetSideHeight( nSide)) ; if ( ! CreatePolygonInBox( ptQ, vtN5, nSide, plyOppo2)) return false ; } else plyOppo2 = plyOppo ; // altre facce Point3d ptQ = ptP + vtN1 * dLength + Y_AX * dSpostY - Z_AX * dDepth2 ; Polygon3d plyTop2 ; if ( ! CreatePolygonInBox( ptQ, vtN4, nSide, plyTop2)) return false ; // taglio tra loro le tre facce if ( ! plyFront2.Trim( plyTop2, false, true) || ! plyTop2.Trim( plyFront2, false, false)) return false ; if ( ! plyOppo2.Trim( plyTop2, false, true) || ! plyTop2.Trim( plyOppo2, false, false)) return false ; // creo la trimesh con queste facce PtrOwner pStmDw( CreateSurfTriMesh()) ; if ( IsNull( pStmDw)) return false ; if ( ! DoSewing( pStmDw, plyFront2) || ! DoSewing( pStmDw, plyTop2) || ! DoSewing( pStmDw, plyOppo2)) return false ; pStmDw->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmDw)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // se presenti, aggiungo identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // salvo Id vIds.emplace_back( nId) ; } // eventuale rientro if ( dInside > EPS_SMALL) { // punto di riferimento Point3d ptQ = ptP + vtN1 * dLength + Y_AX * dSpostY ; // faccia lunga Polygon3d plyLong ; if ( ! CreatePolygonInBox( ptQ, ( nInsPos == 0 ? -Y_AX : Y_AX), nSide, plyLong)) return false ; // faccia di contenimento Vector3d vtN3 = -vtN1 ; if ( dRebMit < 0) { vtN3 = -vtN1 + ( nInsPos == 0 ? -Y_AX : Y_AX) ; vtN3.Normalize() ; } Polygon3d plyShort ; if ( ! CreatePolygonInBox( ptQ + vtN1 * max( dRebMit, 0.), vtN3, nSide, plyShort)) return false ; // eventuale altra faccia di contenimento Polygon3d plyOther ; if ( nGroup == 3 || nGroup == 4) { if ( ! CreatePolygonInBox( ptP, vtN1, nSide, plyOther)) return false ; } // taglio tra loro le tre facce if ( ! plyLong.Trim( plyShort, false, true) || ! plyShort.Trim( plyLong, false, false)) return false ; if ( ! plyLong.Trim( plyOther, false, true) || ! plyOther.Trim( plyLong, false, false)) return false ; // creo la trimesh con queste facce PtrOwner pStmSd( CreateSurfTriMesh()) ; if ( IsNull( pStmSd)) return false ; if ( ! DoSewing( pStmSd, plyLong) || ! DoSewing( pStmSd, plyShort) || ! DoSewing( pStmSd, plyOther)) return false ; pStmSd->DoCompacting( STM_COMPACT_APPROX) ; // inserisco la superficie nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmSd)) ; if ( nId == GDB_ID_NULL) return false ; // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // se presenti, aggiungo identificativi di geometrie ausiliarie SetAuxId( nId, {nAuxId}) ; // salvo Id vIds.emplace_back( nId) ; } // se non è stata inserita alcuna geometria if ( vIds.empty()) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // assegnazione geometria principale m_nProcId = vIds.front() ; vIds.erase( vIds.begin()) ; // eventuali riferimenti reciproci if ( ! vIds.empty()) SetMainAdjId( m_nProcId, vIds) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddFreeContour( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 14) 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 = 0 ; // P05 (solo per start) double dAng = vdPar[4] ; // P06 int nNextId = lround( vdPar[7]) ; // P09 bool bPocket = false ; // P07 (solo per start) int nContType = lround( vdPar[11]) ; // P13 int nContData = lround( vdPar[12]) ; // P14 double dContPar = vdPar[13] ; // P15 // se inizio del contorno... if ( nType == FreeContourEnt::START || nType == FreeContourEnt::START_CNT0) { // assegno e verifico lo spessore (se non attivo riferimento aggiuntivo) dDepth = vdPar[3] ; if ( frRef.GetType() == Frame3d::TOP && ( dDepth < EPS_SMALL || dDepth + vdPar[2] > GetSideHeight( nSide))) dDepth = GetSideHeight( nSide) + vdPar[2] + frRef.Orig().z ; // assegno flag di svuotatura bPocket = ( lround( vdPar[5]) == 1) ; // assegno eventuale riferimento a secondo percorso int nOtherId = -1 ; if ( nType == FreeContourEnt::START_CNT0) nOtherId = lround( vdPar[4]) ; // inserisco negli inizi m_FcStart.emplace_back( nGroup, nSide, dDepth, bPocket, nContType, nContData, dContPar, sDes, frRef, vsUAtt, nProcId, nOtherId) ; } // angolo di fianco (in realtà serve solo per lo start di singolo percorso) if ( nType == FreeContourEnt::START || nType == FreeContourEnt::START_CNT0 || nType == FreeContourEnt::START_CNT1) { // se angolo di fianco non definito, assegno default if ( abs( dAng - FC_SIDEANG_NONE) < EPS_ANG_SMALL) dAng = FC_SIDEANG_DEF ; } // aggiungo i dati alla coda m_FcData.emplace_back( nType, ptP, ptM, dAng, nProcId, nNextId) ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::AddVariant( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // verifica dei parametri if ( vdPar.size() < 2) return false ; // assegnazione parametri Vector3d vtMove( vdPar[0], vdPar[1], 0) ; // P01, P02 // recupero il codice identificativo int nCode = 0 ; FromString( sDes, nCode) ; // inserimento di geometria custom int nId = GDB_ID_NULL ; INTVECTOR vAdjIds ; INTVECTOR vAuxIds ; string sFilePath = m_sBtlAuxDir + "/" + VARIANT_BASENAME + ToString( nCode, 1) + ".nge" ; int nGrp = m_pGDB->InsertGroup( GDB_ID_NULL, GDB_ID_ROOT, GDB_FIRST_SON, GLOB_FRM) ; if ( nGrp != GDB_ID_NULL && m_pGDB->SetLevel( nGrp, GDB_LV_TEMP) && m_pGDB->Load( sFilePath, nGrp)) { int nLay = m_pGDB->GetFirstNameInGroup( m_pGDB->GetFirstNameInGroup( nGrp, VARIANT_PART), VARIANT_LAYER) ; if ( nLay != GDB_ID_NULL) { nId = m_pGDB->GetFirstInGroup( nLay) ; int nEnt = nId ; while ( nEnt != GDB_ID_NULL) { // recupero il successivo int nNextEnt = m_pGDB->GetNext( nEnt) ; // aggiusto la posizione m_pGDB->TranslateGlob( nEnt, vtMove) ; m_pGDB->Relocate( nEnt, m_nProcsId) ; m_pGDB->GetGeoObj( nEnt)->ToGlob( GetSideFrame( nSide)) ; // se non è l'entità principale if ( nEnt != nId) { // se aggiuntivo int nEntProc = 0 ; if ( m_pGDB->GetInfo( nEnt, IKEY_PROC, nEntProc)) vAdjIds.push_back( nEnt) ; // altrimenti ausiliario else vAuxIds.push_back( nEnt) ; } // passo al successivo nEnt = nNextEnt ; } } } m_pGDB->Erase( nGrp) ; // se non è stata inserita alcuna geometria if ( nId == GDB_ID_NULL) { // inserisco superficie vuota come marcatore InsertEmptySurface( nGroup, nProc, nSide, sDes, nProcId, GLOB_FRM, vnDPar, vdPar, vsUAtt) ; // messaggio di warning in log string sOut = " Warning : Empty Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) + ") on line " + ToString( m_nBtlLine) ; LOG_WARN( GetEExLogger(), sOut.c_str()) return true ; } // nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; // aggiorno eventuali geometrie ausiliarie CopyTaskId( nId, vAuxIds) ; // eventuali riferimenti reciproci SetMainAdjId( nId, vAdjIds) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- ICurveComposite* BtlGeom::GetFreeContourCurve( int nProcId, const Frame3d& frRef, bool bOnlyStartOk) { // ricerca del punto di inizio int nStart = -1 ; for ( int i = 0 ; i < int( m_FcData.size()) ; ++ i) { if ( m_FcData[i].nId == nProcId) { nStart = i ; break ; } } // se non trovato, esco if ( nStart == -1) return nullptr ; // creo la lista dei punti con questo inizio FCEDEQUE fcData ; for ( int i = nStart ; i != -1 ;) { fcData.emplace_back( m_FcData[i]) ; fcData.back().ptP.ToGlob( frRef) ; if ( fcData.back().nType == FreeContourEnt::ARC) fcData.back().ptM.ToGlob( frRef) ; m_FcData.erase( m_FcData.begin() + i) ; int nNextId = fcData.back().nNextId ; if ( nNextId == 0) break ; i = - 1 ; for ( int j = 0 ; j < int( m_FcData.size()) && i == -1 ; ++ j) { if ( m_FcData[j].nId == nNextId) i = j ; } if ( i == -1) break ; } // se ammesso solo inizio e così è, aggiungo punto molto vicino if ( bOnlyStartOk && fcData.size() == 1) { fcData.emplace_back( FreeContourEnt( FreeContourEnt::LINE, fcData[0].ptP + Vector3d( 1, 0, 0), ORIG, 0, 0, 0)) ; } // se ammesso solo inizio e due soli punti coincidenti uniti da linea, sposto il secondo come sopra else if ( bOnlyStartOk && fcData.size() == 2 && fcData[1].nType == FreeContourEnt::LINE && AreSamePointApprox( fcData[0].ptP, fcData[1].ptP)) { fcData[1].ptP = fcData[0].ptP + Vector3d( 1, 0, 0) ; } // costruisco il contorno libero PtrOwner pCrv( CurveFromFces( fcData)) ; if ( IsNull( pCrv)) return nullptr ; // imposto l'estrusione pCrv->SetExtrusion( frRef.VersZ()) ; return ( Release( pCrv)) ; } //---------------------------------------------------------------------------- bool BtlGeom::AdjustFreeContourCurve( ICurve* pCrv, int nSide, bool& bClosed, bool& bEndsOnOrOutCont) { // verifico validità curva if ( pCrv == nullptr) return false ; // verifico se curva chiusa (non interessa la posizione degli estremi) bClosed = pCrv->IsClosed() ; if ( bClosed) { bEndsOnOrOutCont = false ; return true ; } // verifico se gli estremi sono sul bordo della faccia Point3d ptStart ; pCrv->GetStartPoint( ptStart) ; Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ; bool bStartOn = IsPointNearFaceContour( ptStart, nSide) ; bool bStartOut = ( ! bStartOn && IsPointOutFaceContour( ptStart, nSide)) ; bool bEndOn = IsPointNearFaceContour( ptEnd, nSide) ; bool bEndOut = ( ! bEndOn && IsPointOutFaceContour( ptEnd, nSide)) ; bEndsOnOrOutCont = ( ( bStartOn || bStartOut) && ( bEndOn || bEndOut)) ; // eventuali aggiustamenti degli estremi if ( bStartOn && bEndsOnOrOutCont && ! IsPointOnFaceContour( ptStart, nSide)) { SetPointOnFaceContour( ptStart, nSide) ; pCrv->ModifyStart( ptStart) ; } if ( bEndOn && bEndsOnOrOutCont && ! IsPointOnFaceContour( ptEnd, nSide)) { SetPointOnFaceContour( ptEnd, nSide) ; pCrv->ModifyEnd( ptEnd) ; } return true ; } //---------------------------------------------------------------------------- bool BtlGeom::VerifyFreeContourCurveSideAng( const ICurveComposite* pCrvCompo) { if ( pCrvCompo == nullptr) return false ; bool bSideAng = false ; for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { int nAng ; if ( pCrvCompo->GetCurveTempProp( i, nAng) && abs( nAng) > 10) { bSideAng = true ; break ; } } return bSideAng ; } //---------------------------------------------------------------------------- bool BtlGeom::GetFreeContourCurveSideAngles( const ICurveComposite* pCrvCompo, DBLVECTOR& vSideAng) { if ( pCrvCompo == nullptr) return false ; for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { int nAng = 0 ; pCrvCompo->GetCurveTempProp( i, nAng) ; vSideAng.emplace_back( nAng / 1000.) ; } return true ; } //---------------------------------------------------------------------------- static ISurfTriMesh* MyCreateSubSurfTm( const ISurfTriMesh* pStm, const INTVECTOR& vTria) { StmFromTriangleSoup StmFts ; if ( ! StmFts.Start()) return nullptr ; for ( int nT : vTria) { Triangle3d Tria ; if ( ! pStm->GetTriangle( nT, Tria) || ! StmFts.AddTriangle( Tria)) return nullptr ; } // valido la superficie e calcolo le adiacenze if ( ! StmFts.End()) return nullptr ; // restituisco la superficie return StmFts.GetSurf() ; } //---------------------------------------------------------------------------- ISurfTriMesh* BtlGeom::CreateOneCurveFreeContour( const ICurveComposite* pCrvCompo) { // costruzione della superficie PtrOwner pStm ; // estrusione e spessore Vector3d vtExtr ; pCrvCompo->GetExtrusion( vtExtr) ; double dThick ; pCrvCompo->GetThickness( dThick) ; // Se ci sono lati con angolo di fianco if ( VerifyFreeContourCurveSideAng( pCrvCompo)) { const double ADD_LEN = max( 500., 2 * abs( dThick)) ; // verifico se curva aperta o chiusa bool bClosed = pCrvCompo->IsClosed() ; // vettore delle superfici trimesh ISURFTMPOVECTOR vpStm ; // creo la superficie opportuna per ogni curva const ICurve* pCrv = pCrvCompo->GetFirstCurve() ; while ( pCrv != nullptr) { // recupero l'angolo di fianco double dAng = pCrv->GetTempProp() / 1000.0 ; // creo una composita come copia della curva PtrOwner pBase( CreateCurveComposite()) ; if ( IsNull( pBase) || ! pBase->AddCurve( *pCrv)) return nullptr ; // aggiungo tratto tangente prima Point3d ptS ; Vector3d vtDirS ; if ( pBase->GetStartPoint( ptS) && pBase->GetStartDir( vtDirS)) pBase->AddLine( ptS - ADD_LEN * vtDirS, false) ; // aggiungo tratto tangente dopo Point3d ptE ; Vector3d vtDirE ; if ( pBase->GetEndPoint( ptE) && pBase->GetEndDir( vtDirE)) pBase->AddLine( ptE + ADD_LEN * vtDirE, true) ; // unisco le parti allineate pBase->MergeCurves( 100 * EPS_SMALL, ANG_RIGHT / 6) ; // copio la composita di base PtrOwner pOther( pBase->Clone()) ; if ( IsNull( pOther)) return nullptr ; // eseguo traslazione lungo estrusione pOther->Translate( dThick * vtExtr) ; // se necessario, eseguo offset if ( abs( dAng) > EPS_ANG_SMALL) { double dOffs = dThick * tan( dAng * DEGTORAD) ; pOther->SetExtrusion( vtExtr) ; pOther->SimpleOffset( dOffs, ICurve::OFF_FILLET) ; } // creo la superficie rigata tra le due curve PolyLine plBase, plOther ; if ( ! pBase->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, plBase) || ! pOther->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, plOther)) return nullptr ; PtrOwner pStmCurr( CreateSurfTriMesh()) ; if ( IsNull( pStmCurr) || ! pStmCurr->CreateByTwoCurves( plOther, plBase, ISurfTriMesh::RLT_ISOPAR)) return nullptr ; //pStmCurr->Invert() ; // la aggiungo al vettore di superfici vpStm.emplace_back( Release( pStmCurr)) ; // passo alla curva successiva pCrv = pCrvCompo->GetNextCurve() ; } // trimmo ogni superficie con la precedente e la successiva (tranne prima e ultima se curva aperta) ISURFTMPOVECTOR vpStmOk ; int nOpenStart = ( bClosed ? -1 : 0) ; int nOpenEnd = ( bClosed ? -1 : int( vpStm.size()) - 1) ; for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { // indici di precedente e successiva int h = ( i - 1 < 0 ? int( vpStm.size()) - 1 : i - 1) ; int j = ( i + 1 < int( vpStm.size()) ? i + 1 : 0) ; // inclinazioni int nCurrProp = 0 ; pCrvCompo->GetCurveTempProp( i, nCurrProp) ; double dCurrAng = nCurrProp / 1000.0 ; int nPrevProp = 0 ; pCrvCompo->GetCurveTempProp( h, nPrevProp) ; double dPrevAng = nPrevProp / 1000.0 ; int nNextProp = 0 ; pCrvCompo->GetCurveTempProp( j, nNextProp) ; double dNextAng = nNextProp / 1000.0 ; // superfici temporanee PtrOwner pStmNew1 ; PtrOwner pStmNew2 ; // tipo di angolo con precedente Vector3d vtPrevS ; pCrvCompo->GetCurve( h)->GetEndDir( vtPrevS) ; Vector3d vtNextS ; pCrvCompo->GetCurve( i)->GetStartDir( vtNextS) ; // se prima di percorso aperto oppure tangenti e con identica inclinazione, taglio con faccia ortogonale if ( i == nOpenStart || ( AreSameVectorApprox( vtPrevS, vtNextS) && abs( dPrevAng - dCurrAng) < 1.0)) { Point3d ptS ; pCrvCompo->GetCurve( i)->GetStartPoint( ptS) ; Plane3d plCut ; plCut.Set( ptS, -vtNextS) ; pStmNew1.Set( vpStm[i]->Clone()) ; if ( IsNull( pStmNew1) || ! pStmNew1->Cut( plCut, false)) return nullptr ; } // altrimenti classifico rispetto a precedente else { bool bConvS = ( ( vtPrevS ^ vtNextS) * vtExtr > - EPS_ZERO) ; INTVECTOR vTriaIn1, vTriaOut1, vTriaOnP1, vTriaOnM1, vTriaIndef1 ; PtrOwner pStmTmp( vpStm[i]->Clone()) ; if ( IsNull( pStmTmp) || ! pStmTmp->GetSurfClassification( *vpStm[h], vTriaIn1, vTriaOut1, vTriaOnP1, vTriaOnM1, vTriaIndef1)) return nullptr ; pStmNew1.Set( MyCreateSubSurfTm( pStmTmp, ( bConvS ? vTriaIn1 : vTriaOut1))) ; } // tipo di angolo con successiva Vector3d vtPrevE ; pCrvCompo->GetCurve( i)->GetEndDir( vtPrevE) ; Vector3d vtNextE ; pCrvCompo->GetCurve( j)->GetStartDir( vtNextE) ; // se ultima di percorso aperto oppure tangenti e con identica inclinazione, taglio con faccia ortogonale if ( i == nOpenEnd || ( AreSameVectorApprox( vtPrevE, vtNextE) && abs( dCurrAng - dNextAng) < 1.0)) { Point3d ptE ; pCrvCompo->GetCurve( i)->GetEndPoint( ptE) ; Plane3d plCut ; plCut.Set( ptE, vtPrevE) ; pStmNew2.Set( pStmNew1) ; if ( IsNull( pStmNew2) || ! pStmNew2->Cut( plCut, false)) return nullptr ; } // altrimenti classifico rispetto a successiva else { bool bConvE = ( ( vtPrevE ^ vtNextE) * vtExtr > - EPS_ZERO) ; INTVECTOR vTriaIn2, vTriaOut2, vTriaOnP2, vTriaOnM2, vTriaIndef2 ; if ( IsNull( pStmNew1) || ! pStmNew1->GetSurfClassification( *vpStm[j], vTriaIn2, vTriaOut2, vTriaOnP2, vTriaOnM2, vTriaIndef2)) return nullptr ; pStmNew2.Set( MyCreateSubSurfTm( pStmNew1, ( bConvE ? vTriaIn2 : vTriaOut2))) ; } if ( IsNull( pStmNew2)) return nullptr ; // se la superficie risultante è piatta, la semplifico if ( pStmNew2->GetFacetCount() == 1) { POLYLINEVECTOR vPL ; pStmNew2->GetLoops( vPL) ; if ( vPL.size() != 1) return nullptr ; vPL[0].RemoveAlignedPoints( 2 * EPS_SMALL) ; if ( vPL[0].GetPointNbr() > 3) { PtrOwner pStmNew3( CreateSurfTriMesh()) ; if ( IsNull( pStmNew3) || ! pStmNew3->CreateByFlatContour( vPL[0])) return nullptr ; pStmNew2.Set( pStmNew3) ; } else pStmNew2.Reset() ; } // inserisco la superficie risultante nel vettore delle superfici corrette if ( ! IsNull( pStmNew2)) vpStmOk.emplace_back( Release( pStmNew2)) ; } // unisco le superfici così ottenute for ( int i = 0 ; i < int( vpStmOk.size()) ; ++ i) { if ( IsNull( pStm)) pStm.Set( vpStmOk[i]) ; else pStm->DoSewing( *(vpStmOk[i]), GLOB_FRM, 100 * EPS_SMALL) ; } } // altrimenti è una superficie di estrusione else { // ricavo la spezzata che approssima la curva PolyLine PL ; if ( ! pCrvCompo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL)) return nullptr ; // eseguo strusione pStm.Set( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByExtrusion( PL, vtExtr * dThick)) return nullptr ; pStm->Invert() ; } return Release( pStm) ; } //---------------------------------------------------------------------------- bool BtlGeom::CreateFreeContours( void) { bool bOk = true ; // estraggo i vari contorni liberi semplici while ( ! m_FcStart.empty()) { // assegno i dati del contorno derivanti dal suo inizio int nGroup = m_FcStart[0].nGroup ; int nSide = m_FcStart[0].nSide ; bool bPocket = m_FcStart[0].bPocket ; int nContType = m_FcStart[0].nContType ; int nContData = m_FcStart[0].nContData ; double dContPar = m_FcStart[0].dContPar ; double dDepth = m_FcStart[0].dDepth ; if ( nContType == FCT_PEN) dDepth = PEN_DEPTH ; else if ( nContType == FCT_NAIL) dDepth = NAILING_DEPTH ; else if ( nContType == FCT_LOCKOUT_AREA) dDepth = LOCKOUT_DEPTH ; string sDes = m_FcStart[0].sDes ; Frame3d frRef = m_FcStart[0].frRef ; int nProcId = m_FcStart[0].nId ; int nOtherId = m_FcStart[0].nOtherId ; STRVECTOR vsUAtt = m_FcStart[0].vsUAtt ; // rimuovo questo inizio dalla lista m_FcStart.pop_front() ; // costruisco il contorno libero PtrOwner pCrvCompo( GetFreeContourCurve( nProcId, frRef, nContType == FCT_NAIL)) ; if ( IsNull( pCrvCompo)) break ; // eventuale secondo contorno PtrOwner pCrvCompo2( GetFreeContourCurve( nOtherId, frRef, false)) ; bool bOneCurve = ( IsNull( pCrvCompo2)) ; // dati generali delle curve bool bClosed = false ; bool bEndsOnCont = false ; bool bHCross = false ; // costruzione della superficie PtrOwner pStm ; // se contorno singolo if ( bOneCurve) { // sistemo la curva AdjustFreeContourCurve( pCrvCompo, nSide, bClosed, bEndsOnCont) ; // se previsto, imposto spessore pCrvCompo->SetThickness( -dDepth) ; // verifico se interessa tutto lo spessore della trave perpendicolarmente alla faccia BBox3d b3Crv ; pCrvCompo->GetLocalBBox( b3Crv) ; bHCross = ( ! b3Crv.IsEmpty() && b3Crv.GetMax().z > - EPS_SMALL && b3Crv.GetMin().z < - GetSideHeight( nSide) + EPS_SMALL) ; // se penna o chiodatura e tutta fuori, la porto dentro if ( ( nContType == FCT_PEN || nContType == FCT_NAIL) && ! b3Crv.IsEmpty() && b3Crv.GetMax().z < - GetSideHeight( nSide) + EPS_SMALL) pCrvCompo->Translate( Vector3d( 0, 0, b3Crv.GetMax().z - b3Crv.GetMin().z)) ; // la porto nel riferimento della faccia pCrvCompo->ToGlob( GetSideFrame( nSide)) ; // creo la superficie pStm.Set( CreateOneCurveFreeContour( pCrvCompo)) ; if ( IsNull( pStm)) continue ; if ( nGroup != 4) pStm->Invert() ; // se chiusa e con flag di svuotatura if ( bClosed && bPocket) { Vector3d vtExtr ; pCrvCompo->GetExtrusion( vtExtr) ; double dThick ; pCrvCompo->GetThickness( dThick) ; // ricavo la spezzata che approssima la curva PolyLine PL ; if ( ! pCrvCompo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL)) continue ; // creo la superficie di fondo PtrOwner pPocket( CreateSurfTriMesh()) ; if ( IsNull( pPocket) || ! pPocket->CreateByFlatContour( PL)) continue ; // se necessario, inverto l'orientamento del fondo Vector3d vtN ; if ( pPocket->GetFacetNormal( 0, vtN) && vtExtr * vtN < 0) { pPocket->Invert() ; if ( nGroup != 4) { pStm->Invert() ; pCrvCompo->Invert() ; } } // altrimenti ... else if ( nGroup == 4) { pStm->Invert() ; pCrvCompo->Invert() ; } // la porto in posizione corretta pPocket->Translate( dThick * vtExtr) ; // la unisco alla parte laterale pStm->DoSewing( *pPocket) ; } } // altrimenti doppio contorno else { // sistemo le curva bool bClosed1, bClosed2 ; bool bEndsOnCont1, bEndsOnCont2 ; AdjustFreeContourCurve( pCrvCompo, nSide, bClosed1, bEndsOnCont1) ; AdjustFreeContourCurve( pCrvCompo2, nSide, bClosed2, bEndsOnCont2) ; bClosed = ( bClosed1 && bClosed2) ; bEndsOnCont = ( bEndsOnCont1 && bEndsOnCont2) ; // non ha senso lo spessore di ogni singolo contorno // ingombro delle curve BBox3d b3Crv ; pCrvCompo->GetLocalBBox( b3Crv) ; BBox3d b3Crv2 ; pCrvCompo2->GetLocalBBox( b3Crv2) ; // verifico se la curva 2 è sopra o sotto la 1 bool bTwoBottom = ( b3Crv2.GetMin().z < b3Crv.GetMin().z + EPS_SMALL) ; // verifico se interessano tutto lo spessore della trave perpendicolarmente alla faccia b3Crv.Add( b3Crv2) ; bHCross = ( ! b3Crv.IsEmpty() && b3Crv.GetMax().z > - EPS_SMALL && b3Crv.GetMin().z < - GetSideHeight( nSide) + EPS_SMALL) ; // li porto nel riferimento della faccia pCrvCompo->ToGlob( GetSideFrame( nSide)) ; pCrvCompo2->ToGlob( GetSideFrame( nSide)) ; // ricavo le spezzate che li approssima PolyLine PL, PL2 ; if ( ! pCrvCompo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL) || ! pCrvCompo2->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL2)) continue ; // verifico se le due curve sono una la traslata dell'altra e ne setto l'estrusione di conseguenza double dS1, dE1 ; pCrvCompo->GetDomain( dS1, dE1) ; double dS2, dE2 ; pCrvCompo2->GetDomain( dS2, dE2) ; if ( abs( dS1 - dS2) < EPS_SMALL && abs( dE1 - dE2) < EPS_SMALL) { Point3d ptS1 ; pCrvCompo->GetStartPoint( ptS1) ; Point3d ptS2 ; pCrvCompo2->GetStartPoint( ptS2) ; Vector3d vtDiffS = ( bTwoBottom ? ptS1 - ptS2 : ptS2 - ptS1) ; Point3d ptM1 ; pCrvCompo->GetMidPoint( ptM1) ; Point3d ptM2 ; pCrvCompo2->GetMidPoint( ptM2) ; Vector3d vtDiffM = ( bTwoBottom ? ptM1 - ptM2 : ptM2 - ptM1) ; Point3d ptE1 ; pCrvCompo->GetEndPoint( ptE1) ; Point3d ptE2 ; pCrvCompo2->GetEndPoint( ptE2) ; Vector3d vtDiffE = ( bTwoBottom ? ptE1 - ptE2 : ptE2 - ptE1) ; if ( AreSameVectorEpsilon( vtDiffS, vtDiffM, 500 * EPS_SMALL) && AreSameVectorEpsilon( vtDiffS, vtDiffE, 500 * EPS_SMALL)) { Vector3d vtDiff = ( vtDiffS + vtDiffM + vtDiffE) / 3 ; pCrvCompo->SetExtrusion( vtDiff) ; pCrvCompo2->SetExtrusion( -vtDiff) ; double dDiff = vtDiff.Len() * ( bTwoBottom ? 1 : -1) ; pCrvCompo->SetThickness( -dDiff) ; pCrvCompo2->SetThickness( -dDiff) ; } } // creo la superficie rigata corrispondente pStm.Set( CreateSurfTriMesh()) ; if ( IsNull( pStm)) { bOk = false ; continue ; } if ( pStm->CreateByTwoCurves( PL, PL2, ISurfTriMesh::RLT_ISOPAR)) { if ( ( nGroup == 4 && bTwoBottom) || ( nGroup != 4 && ! bTwoBottom)) pStm->Invert() ; // se chiusa e con flag di svuotatura if ( bClosed && bPocket) { // creo la superficie di fondo PtrOwner pPocket( CreateSurfTriMesh()) ; if ( IsNull( pPocket) || ! pPocket->CreateByFlatContour( ( ! bTwoBottom ? PL : PL2))) continue ; // se necessario, inverto l'orientamento del fondo Vector3d vtExtr ; pCrvCompo->GetExtrusion( vtExtr) ; Vector3d vtN ; if ( pPocket->GetFacetNormal( 0, vtN) && vtExtr * vtN < 0) pPocket->Invert() ; // altrimenti... else if ( ( nGroup == 4 && bTwoBottom) || ( nGroup != 4 && ! bTwoBottom)) { pStm->Invert() ; pCrvCompo->Invert() ; } // la unisco alla parte laterale pStm->DoSewing( *pPocket) ; } } else { bOk = false ; pStm.Set( CreateSurfTriMesh()) ; if ( IsNull( pStm)) continue ; pStm->AdjustTopology() ; string sOut = " Error in FreeContour " + ToString( nProcId) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) } } pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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) continue ; // eseguo trim con le facce della trave if ( nContType != FCT_LOCKOUT_AREA) TrimFlatCurveWithBox( pCrvCompo, FC_OUT_CRV_TOL) ; else { // chiusura della curva, se necessario pCrvCompo->Close() ; // eseguo trim con ricostruzione di curva chiusa pCrvCompo.Set( ConvertCurveToComposite( TrimFlatCurveWithBoxEx( Release( pCrvCompo), 10 * EPS_SMALL))) ; if ( IsNull( pCrvCompo)) continue ; } // recupero eventuali angoli di fianco DBLVECTOR vSideAng ; if ( bOneCurve && VerifyFreeContourCurveSideAng( pCrvCompo)) GetFreeContourCurveSideAngles( pCrvCompo, vSideAng) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCompo)) ; if ( nTId != GDB_ID_NULL && vSideAng.size() > 0) m_pGDB->SetInfo( nTId, IKEY_SIDEANGS, vSideAng) ; // inserisco eventuale seconda curva int nT2Id = GDB_ID_NULL ; if ( ! bOneCurve) { nT2Id = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCompo2)) ; } // nome e info con tipo SetNameAndInfo( nId, nGroup, 250, nSide, sDes, nProcId) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametro affondamento m_pGDB->SetInfo( nId, IKEY_DEPTH, dDepth) ; // segnalo se svuotatura if ( bClosed && bPocket) m_pGDB->SetInfo( nId, IKEY_POCKET, 1) ; // segnalo se rigata if ( ! bOneCurve) m_pGDB->SetInfo( nId, IKEY_RULED, 1) ; // assegno i parametri del contorno if ( nContType > 0 || ( nContType >= 0 && nContData != 0)) m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ; if ( nContData != 0) m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ; if ( abs( dContPar) > EPS_SMALL) m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ; // attributi utente SetUserAttributes( nId, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId, nT2Id}) ; // imposto flag per non fare trim if ( ! ((( bEndsOnCont || bClosed) && bHCross) || ( bClosed && bPocket))) m_pGDB->SetInfo( nId, IKEY_TRIM, 0) ; } // verifico che la coda dei punti sia vuota if ( m_FcData.size() > 0) { string sOut = " Error : found unused data in Free Contour (PId=" + ToString( m_FcData[0].nId) + ")" ; LOG_ERROR( GetEExLogger(), sOut.c_str()) bOk = false ; } // in ogni caso le svuoto m_FcStart.clear() ; m_FcData.clear() ; return bOk ; } //---------------------------------------------------------------------------- bool BtlGeom::AddOneFreeContour( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt, int nCrvId, int nCrv2Id) { // reset dell'identificativo della geometria principale della feature m_nProcId = GDB_ID_NULL ; // verifica dei parametri if ( vdPar.size() < 14) return false ; // sistemo i dati double dDepth = vdPar[3] ; // P05 if ( dDepth < EPS_SMALL) dDepth = GetSideHeight( nSide) ; bool bPocket = ( lround( vdPar[5]) == 1) ; ; // P07 int nContType = lround( vdPar[11]) ; // P13 int nContData = lround( vdPar[12]) ; // P14 double dContPar = vdPar[13] ; // P15 // copio la prima curva PtrOwner pCrvCompo ; if ( m_pGDB->GetGeoType( nCrvId) & GEO_CURVE) { pCrvCompo.Set( CreateCurveComposite()) ; if ( ! pCrvCompo->CopyFrom( m_pGDB->GetGeoObj( nCrvId))) pCrvCompo.Reset() ; } // copio eventuale seconda curva PtrOwner pCrvCompo2 ; if ( m_pGDB->GetGeoType( nCrv2Id) & GEO_CURVE) { pCrvCompo2.Set( CreateCurveComposite()) ; if ( ! pCrvCompo2->CopyFrom( m_pGDB->GetGeoObj( nCrv2Id))) pCrvCompo2.Reset() ; } // numero di curve int nCrvCnt = 0 ; if ( ! IsNull( pCrvCompo)) { ++ nCrvCnt ; if ( ! IsNull( pCrvCompo2)) ++ nCrvCnt ; } // dati generali delle curve bool bClosed = false ; bool bEndsOnCont = false ; bool bHCross = false ; // costruzione della superficie bool bOk = true ; PtrOwner pStm ; // se nessuna curva if ( nCrvCnt == 0) { bOk = false ; } // se altrimenti solo prima curva else if ( nCrvCnt == 1) { // assegno eventuali angoli di fianco { DBLVECTOR vSideAng ; if ( m_pGDB->GetInfo( nCrvId, IKEY_SIDEANGS, vSideAng)) { for ( int i = 0 ; i < int( vSideAng.size()) ; ++ i) pCrvCompo->SetCurveTempProp( i, int( vSideAng[i] * 1000)) ; } } // esprimo la curva nel riferimento della faccia Frame3d frSide = GetSideFrame( nSide) ; pCrvCompo->ToLoc( frSide) ; // sistemo la curva AdjustFreeContourCurve( pCrvCompo, nSide, bClosed, bEndsOnCont) ; // se previsto, imposto spessore pCrvCompo->SetThickness( -dDepth) ; // verifico se interessa tutto lo spessore della trave perpendicolarmente alla faccia BBox3d b3Crv ; pCrvCompo->GetLocalBBox( b3Crv) ; bHCross = ( ! b3Crv.IsEmpty() && b3Crv.GetMax().z > - EPS_SMALL && b3Crv.GetMin().z < - GetSideHeight( nSide) + EPS_SMALL) ; // se penna o chiodatura e tutta fuori, la porto dentro if ( ( nContType == FCT_PEN || nContType == FCT_NAIL) && ! b3Crv.IsEmpty() && b3Crv.GetMax().z < - GetSideHeight( nSide) + EPS_SMALL) pCrvCompo->Translate( Vector3d( 0, 0, b3Crv.GetMax().z - b3Crv.GetMin().z)) ; // la porto nel riferimento della faccia pCrvCompo->ToGlob( frSide) ; // creo la superficie pStm.Set( CreateOneCurveFreeContour( pCrvCompo)) ; bOk = bOk && ! IsNull( pStm) ; if ( bOk) { if ( nGroup != 4) pStm->Invert() ; // se chiusa e con flag di svuotatura if ( bClosed && bPocket) { Vector3d vtExtr ; pCrvCompo->GetExtrusion( vtExtr) ; double dThick ; pCrvCompo->GetThickness( dThick) ; // ricavo la spezzata che approssima la curva PolyLine PL ; if ( pCrvCompo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL)) { // creo la superficie di fondo PtrOwner pPocket( CreateSurfTriMesh()) ; if ( ! IsNull( pPocket) && pPocket->CreateByFlatContour( PL)) { // se necessario, inverto l'orientamento del fondo Vector3d vtN ; if ( pPocket->GetFacetNormal( 0, vtN) && vtExtr * vtN < 0) { pPocket->Invert() ; if ( nGroup == 3) { pStm->Invert() ; pCrvCompo->Invert() ; } } // altrimenti ... else if ( nGroup == 4) { pStm->Invert() ; pCrvCompo->Invert() ; } // la porto in posizione corretta pPocket->Translate( dThick * vtExtr) ; // la unisco alla parte laterale pStm->DoSewing( *pPocket) ; } } } } } // altrimenti entrambe le curve else { // porto le curve nel riferimento della faccia Frame3d frSide = GetSideFrame( nSide) ; pCrvCompo->ToLoc( frSide) ; pCrvCompo2->ToLoc( frSide) ; // aggiusto la posizione rispetto alla faccia ( da fare !!!!) // sistemo le curva bool bClosed1, bClosed2 ; bool bEndsOnCont1, bEndsOnCont2 ; AdjustFreeContourCurve( pCrvCompo, nSide, bClosed1, bEndsOnCont1) ; AdjustFreeContourCurve( pCrvCompo2, nSide, bClosed2, bEndsOnCont2) ; bClosed = ( bClosed1 && bClosed2) ; bEndsOnCont = ( bEndsOnCont1 && bEndsOnCont2) ; // non ha senso lo spessore di ogni singolo contorno // ingombro delle curve BBox3d b3Crv ; pCrvCompo->GetLocalBBox( b3Crv) ; BBox3d b3Crv2 ; pCrvCompo2->GetLocalBBox( b3Crv2) ; // verifico se la curva 2 è sopra o sotto la 1 bool bTwoBottom = ( b3Crv2.GetMin().z < b3Crv.GetMin().z + EPS_SMALL) ; // verifico se interessano tutto lo spessore della trave perpendicolarmente alla faccia b3Crv.Add( b3Crv2) ; bHCross = ( ! b3Crv.IsEmpty() && b3Crv.GetMax().z > - EPS_SMALL && b3Crv.GetMin().z < - GetSideHeight( nSide) + EPS_SMALL) ; // li porto nel riferimento della faccia pCrvCompo->ToGlob( frSide) ; pCrvCompo2->ToGlob( frSide) ; // ricavo le spezzate che li approssima PolyLine PL, PL2 ; if ( pCrvCompo->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL) && pCrvCompo2->ApproxWithLines( CRV_LIN_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL2)) { // verifico se le due curve sono una la traslata dell'altra e ne setto l'estrusione di conseguenza double dS1, dE1 ; pCrvCompo->GetDomain( dS1, dE1) ; double dS2, dE2 ; pCrvCompo2->GetDomain( dS2, dE2) ; if ( abs( dS1 - dS2) < EPS_SMALL && abs( dE1 - dE2) < EPS_SMALL) { Point3d ptS1 ; pCrvCompo->GetStartPoint( ptS1) ; Point3d ptS2 ; pCrvCompo2->GetStartPoint( ptS2) ; Vector3d vtDiffS = ( bTwoBottom ? ptS1 - ptS2 : ptS2 - ptS1) ; Point3d ptM1 ; pCrvCompo->GetMidPoint( ptM1) ; Point3d ptM2 ; pCrvCompo2->GetMidPoint( ptM2) ; Vector3d vtDiffM = ( bTwoBottom ? ptM1 - ptM2 : ptM2 - ptM1) ; Point3d ptE1 ; pCrvCompo->GetEndPoint( ptE1) ; Point3d ptE2 ; pCrvCompo2->GetEndPoint( ptE2) ; Vector3d vtDiffE = ( bTwoBottom ? ptE1 - ptE2 : ptE2 - ptE1) ; if ( AreSameVectorEpsilon( vtDiffS, vtDiffM, 500 * EPS_SMALL) && AreSameVectorEpsilon( vtDiffS, vtDiffE, 500 * EPS_SMALL)) { Vector3d vtDiff = ( vtDiffS + vtDiffM + vtDiffE) / 3 ; pCrvCompo->SetExtrusion( vtDiff) ; pCrvCompo2->SetExtrusion( -vtDiff) ; double dDiff = vtDiff.Len() * ( bTwoBottom ? 1 : -1) ; pCrvCompo->SetThickness( -dDiff) ; pCrvCompo2->SetThickness( -dDiff) ; } } // creo la superficie rigata corrispondente pStm.Set( CreateSurfTriMesh()) ; bOk = bOk && ! IsNull( pStm) && pStm->CreateByTwoCurves( PL, PL2, ISurfTriMesh::RLT_ISOPAR) ; if ( bOk) { if ( ( nGroup == 4 && bTwoBottom) || ( nGroup != 4 && ! bTwoBottom)) pStm->Invert() ; // se chiusa e con flag di svuotatura if ( bClosed && bPocket) { // creo la superficie di fondo PtrOwner pPocket( CreateSurfTriMesh()) ; if ( ! IsNull( pPocket) && pPocket->CreateByFlatContour( ( ! bTwoBottom ? PL : PL2))) { // se necessario, inverto l'orientamento del fondo Vector3d vtExtr ; pCrvCompo->GetExtrusion( vtExtr) ; Vector3d vtN ; if ( pPocket->GetFacetNormal( 0, vtN) && vtExtr * vtN < 0) pPocket->Invert() ; // altrimenti... else if ( ( nGroup == 4 && bTwoBottom) || ( nGroup != 4 && ! bTwoBottom)) { pStm->Invert() ; pCrvCompo->Invert() ; } // la unisco alla parte laterale pStm->DoSewing( *pPocket) ; } } } } } // in caso di errore if ( ! bOk) { pStm.Set( CreateSurfTriMesh()) ; if ( IsNull( pStm)) return false ; pStm->AdjustTopology() ; string sOut = " Error in FreeContour " + ToString( nProcId) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) } // sistemo pStm->DoCompacting( STM_COMPACT_APPROX) ; // 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 ; // eseguo trim con le facce della trave TrimFlatCurveWithBox( pCrvCompo, FC_OUT_CRV_TOL) ; // recupero eventuali angoli di fianco DBLVECTOR vSideAng ; if ( nCrvCnt == 1 && VerifyFreeContourCurveSideAng( pCrvCompo)) GetFreeContourCurveSideAngles( pCrvCompo, vSideAng) ; // inserisco la curva nel DB geometrico int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCompo)) ; if ( nTId != GDB_ID_NULL && vSideAng.size() > 0) m_pGDB->SetInfo( nTId, IKEY_SIDEANGS, vSideAng) ; // inserisco eventuale seconda curva int nT2Id = GDB_ID_NULL ; if ( nCrvCnt == 2) nT2Id = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pCrvCompo2)) ; // nome e info con tipo SetNameAndInfo( nId, nGroup, 250, nSide, sDes, nProcId) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // parametro affondamento m_pGDB->SetInfo( nId, IKEY_DEPTH, dDepth) ; // segnalo se svuotatura if ( bClosed && bPocket) m_pGDB->SetInfo( nId, IKEY_POCKET, 1) ; // segnalo se rigata if ( nCrvCnt == 2) m_pGDB->SetInfo( nId, IKEY_RULED, 1) ; // assegno i parametri del contorno if ( nContType > 0 || ( nContType >= 0 && nContData != 0)) m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ; if ( nContData != 0) m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ; if ( abs( dContPar) > EPS_SMALL) m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ; // attributi utente SetUserAttributes( nId, vsUAtt) ; // identificativi di geometrie ausiliarie SetAuxId( nId, {nTId, nT2Id}) ; // imposto flag per non fare trim if ( ! ((( bEndsOnCont || bClosed) && bHCross) || ( bClosed && bPocket))) m_pGDB->SetInfo( nId, IKEY_TRIM, 0) ; m_nProcId = nId ; return true ; } //---------------------------------------------------------------------------- bool BtlGeom::CreatePolygonInBox( const Point3d& ptP, const Vector3d& vtN, int nSide, Polygon3d& Polyg, double dMatMin, double dAreaMin) { // calcolo il piano Plane3d plPlane ; if ( ! plPlane.Set( ptP, vtN)) 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) if ( ! Polyg.FromPlaneTrimmedWithBox( plPlane, ORIG, ORIG + m_vtDim, true, ( dMatMin < EPS_SMALL))) return false ; // verifico che il materiale lasciato non sia inferiore al minimo VerifyPolygonBackMat( Polyg, dMatMin, dAreaMin) ; return true ; } //---------------------------------------------------------------------------- double BtlGeom::GetPlaneElevation( const Plane3d& plPlane) { // determino l'elevazione della trave sopra la faccia del poligono (poligono limitato solo dalla trave) double dElev = 0 ; PNTVECTOR vVtB = { Point3d( 0, 0, 0), Point3d( m_vtDim.x, 0, 0), Point3d( m_vtDim.x, m_vtDim.y, 0), Point3d( 0, m_vtDim.y, 0), Point3d( 0, 0, m_vtDim.z), Point3d( m_vtDim.x, 0, m_vtDim.z), Point3d( m_vtDim.x, m_vtDim.y, m_vtDim.z), Point3d( 0, m_vtDim.y, m_vtDim.z)} ; for ( auto& ptP : vVtB) { double dTmp = DistPointPlane( ptP, plPlane) ; if ( dTmp > dElev) dElev = dTmp ; } return dElev ; } //---------------------------------------------------------------------------- bool BtlGeom::TrimPolygons( Polygon3d& plyP1, Polygon3d& plyP2, bool bInVsOut, bool bOnEq) { return ( plyP1.Trim( plyP2, bInVsOut, bOnEq) && plyP2.Trim( plyP1, bInVsOut, bOnEq)) ; } //---------------------------------------------------------------------------- bool BtlGeom::VerifyPolygonSize( Polygon3d& plyP, double dMinDim) { if ( ! plyP.IsValid()) return false ; if ( plyP.GetSideCount() == 0) return true ; double dPerim = plyP.GetPerimeter() ; double dArea = plyP.GetArea() ; if ( dPerim > EPS_SMALL && 2 * dArea / dPerim >= dMinDim) return true ; plyP.Clear() ; return false ; } //---------------------------------------------------------------------------- bool BtlGeom::VerifyPolygonBackMat( Polygon3d& plyP, double dMatMin, double dAreaMin) { // verifico esistenza poligono limitato if ( plyP.GetSideCount() == 0) return true ; // verifico l'area minima per il controllo double dArea = plyP.GetArea() ; if ( dArea > dAreaMin) dMatMin = min( dMatMin, FACE_ZERO_BACK_MAT) ; // verifico che il materiale lasciato non sia inferiore al minimo for ( int nS = BTL_SIDE_FRONT ; nS <= BTL_SIDE_RIGHT ; ++ nS) { // confronto con ogni faccia del box della trave quasi opposta Plane3d plFace = GetSidePlane( nS) ; if ( plyP.GetPlane().GetVersN() * plFace.GetVersN() < -0.5) { // cerco minima profondità negativa sui vertici e sul punto centrale PNTVECTOR vVert = plyP.GetVertices() ; double dMinDist = 0 ; for ( const auto& ptV : vVert) { double dDist = DistPointPlane( ptV, plFace) ; if ( dDist < dMinDist) dMinDist = dDist ; } Point3d ptCen = plyP.GetCentroid() ; double dDist = DistPointPlane( ptCen, plFace) ; if ( dDist < dMinDist) dMinDist = dDist ; // se profondità non sufficicente, allora elimino la faccia if ( dMinDist >= - abs( dMatMin) + EPS_ZERO) { plyP.Clear() ; return false ; } } } return true ; } //---------------------------------------------------------------------------- bool BtlGeom::VerifyPolygonWithPolygon( Polygon3d& plyP, const Polygon3d& plyRef, bool bInVsOut, double dMatMin) { // verifico sui poligoni if ( ! plyP.IsValid()) return false ; if ( plyRef.GetSideCount() < 3) return true ; // controllo soglia dMatMin = max( dMatMin, EPS_SMALL) ; // Se richiesto interno, verifico che il poligono stia dentro almeno della quantità minima if ( bInVsOut) { double dMinDist = INFINITO ; for ( auto& ptV : plyP.GetVertices()) { double dDist = DistPointPlane( ptV, plyRef.GetPlane()) ; if ( dDist < dMinDist) dMinDist = dDist ; } return ( dMinDist <= -dMatMin) ; } // altrimenti richiesto esterno, verifico che il poligono stia fuori almeno della quantità minima else { double dMaxDist = -INFINITO ; for ( auto& ptV : plyP.GetVertices()) { double dDist = DistPointPlane( ptV, plyRef.GetPlane()) ; if ( dDist > dMaxDist) dMaxDist = dDist ; } return ( dMaxDist >= dMatMin) ; } } //---------------------------------------------------------------------------- bool BtlGeom::VerifyPolygonWithPolygons( Polygon3d& plyP, const Polygon3d& plyRef1, const Polygon3d& plyRef2, bool bInVsOut, double dMatMin) { return ( VerifyPolygonWithPolygon( plyP, plyRef1, bInVsOut, dMatMin) && VerifyPolygonWithPolygon( plyP, plyRef2, bInVsOut, dMatMin)) ; } //---------------------------------------------------------------------------- bool BtlGeom::VerifyPolygonWithPolygons( Polygon3d& plyP, const Polygon3d& plyRef1, const Polygon3d& plyRef2, const Polygon3d& plyRef3, bool bInVsOut, double dMatMin) { return ( VerifyPolygonWithPolygon( plyP, plyRef1, bInVsOut, dMatMin) && VerifyPolygonWithPolygon( plyP, plyRef2, bInVsOut, dMatMin) && VerifyPolygonWithPolygon( plyP, plyRef3, bInVsOut, dMatMin)) ; } //---------------------------------------------------------------------------- bool BtlGeom::VerifyPolygonWithPolygons( Polygon3d& plyP, const Polygon3d& plyRef1, const Polygon3d& plyRef2, const Polygon3d& plyRef3, const Polygon3d& plyRef4, bool bInVsOut, double dMatMin) { return ( VerifyPolygonWithPolygon( plyP, plyRef1, bInVsOut, dMatMin) && VerifyPolygonWithPolygon( plyP, plyRef2, bInVsOut, dMatMin) && VerifyPolygonWithPolygon( plyP, plyRef3, bInVsOut, dMatMin) && VerifyPolygonWithPolygon( plyP, plyRef4, bInVsOut, dMatMin)) ; } //---------------------------------------------------------------------------- bool BtlGeom::TrimConcaveFaces( POLYGVECTOR& vPolyg, const INTMATRIX& vAdjac, double dMatMin, double dAreaMin) { POLYGVECTOR vOrigPolyg = vPolyg ; bool bToTrim = true ; for ( int h = 0 ; bToTrim && h < int( vPolyg.size()) ; ++ h) { vPolyg = vOrigPolyg ; bToTrim = false ; for ( int i = 0 ; i < int( vPolyg.size()) ; ++ i) { for ( int j = 0 ; j < int( vAdjac[i].size()) ; ++ j) { int m = vAdjac[i][j] ; if ( ! vPolyg[i].Trim( vPolyg[m], false, i < m)) return false ; } if ( ! VerifyPolygonBackMat( vPolyg[i], dMatMin, dAreaMin)) { vOrigPolyg[i].Clear() ; bToTrim = true ; break ; } } } return ( ! bToTrim) ; } //---------------------------------------------------------------------------- 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_RIGHT ; ++ i) { Plane3d plFace = GetSidePlane( i) ; pStm->Cut( plFace, true) ; } return true ; } //---------------------------------------------------------------------------- bool BtlGeom::TrimFlatCurveWithBox( ICurve* pCurve, double dLinTol) { // verifico esistenza curva if ( pCurve == nullptr) return false ; // determino il piano della curva Plane3d plPlane ; if ( ! pCurve->IsFlat( plPlane, false, 10 * EPS_SMALL)) return false ; // determino la parte di piano (poligono) compresa nel box della trave Vector3d vtTol( dLinTol, dLinTol, dLinTol) ; Polygon3d Polyg ; if ( ! Polyg.FromPlaneTrimmedWithBox( plPlane, ORIG - vtTol, ORIG + m_vtDim + vtTol, true, true)) 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, EPS_SMALL, 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 ; } //---------------------------------------------------------------------------- ICurve* BtlGeom::TrimFlatCurveWithBoxEx( ICurve* pCurve, double dLinTol) { // verifico esistenza curva PtrOwner< ICurve> pMyCrv( pCurve) ; if ( IsNull( pMyCrv)) return nullptr ; // se la curva è completamente contenuta nel box della trave non va modificata BBox3d b3Crv ; pCurve->GetLocalBBox( b3Crv) ; BBox3d b3Box( ORIG, ORIG + m_vtDim) ; b3Box.Expand( dLinTol + 10 * EPS_SMALL) ; if ( b3Box.Encloses( b3Crv)) return Release( pMyCrv) ; // determino il piano della curva Plane3d plPlane ; if ( ! pCurve->IsFlat( plPlane, false, 10 * EPS_SMALL)) return nullptr ; // determino la parte di piano (poligono) compresa nel box della trave Vector3d vtTol( dLinTol, dLinTol, dLinTol) ; Polygon3d Polyg ; if ( ! Polyg.FromPlaneTrimmedWithBox( plPlane, ORIG - vtTol, ORIG + m_vtDim + vtTol, true, true)) return nullptr ; // creo la regione corrispondente PtrOwner pCrv( CreateCurveComposite()) ; if ( IsNull( pCrv) || ! pCrv->FromPolyLine( Polyg.GetPolyLine())) return nullptr ; PtrOwner pSfr( CreateSurfFlatRegion()) ; if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pCrv))) return nullptr ; // se curva aperta if ( ! pMyCrv->IsClosed()) { // calcolo la classificazione della curva rispetto alla regione CRVCVECTOR ccClass ; if ( ! pSfr->GetCurveClassification( *pMyCrv, EPS_SMALL, ccClass)) return nullptr ; // 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) ; } // considero solo min-max degli intervalli if ( inOk.GetCount() >= 1) { // eseguo il taglio double dParS, dParE ; inOk.GetMinMax( dParS, dParE) ; if ( ! pMyCrv->TrimStartEndAtParam( dParS, dParE)) return nullptr ; } return Release( pMyCrv) ; } // altrimenti curva chiusa else { // creo la regione delimitata dalla curva chiusa PtrOwner pSfrCrv( CreateSurfFlatRegion()) ; if ( IsNull( pSfrCrv) || ! pSfrCrv->AddExtLoop( Release( pMyCrv))) return nullptr ; // eseguo l'intersezione tra le due regioni if ( ! pSfrCrv->Intersect( *pSfr)) return nullptr ; // recupero il contorno esterno della nuova regione PtrOwner pNewCrv( pSfrCrv->GetLoop( 0, 0)) ; return Release( pNewCrv) ; } return nullptr ; } //---------------------------------------------------------------------------- bool BtlGeom::TrimSegmentWithBox( Point3d& ptP1, Point3d& ptP2, double dRad) { // eseguo trim con le facce della trave for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_RIGHT ; ++ i) { // piano della faccia Plane3d plFace = GetSidePlane( i) ; double dHeight = GetSideHeight( i) ; // distanza con segno dei punti dal piano double dDist1 = DistPointPlane( ptP1, plFace) ; double dDist2 = DistPointPlane( ptP2, plFace) ; // se entrambi esterni di più del raggio, segmento da annullare if ( dDist1 > dRad + EPS_SMALL && dDist2 > dRad + EPS_SMALL) return false ; // se entrambi esterni, non devo fare alcunché if ( dDist1 > EPS_SMALL && dDist2 > EPS_SMALL) ; // se primo esterno, devo spostare inizio else if ( dDist1 > EPS_SMALL && ( -dDist2 - dHeight) > -100 * EPS_SMALL) ptP1 = Media( ptP1, ptP2, dDist1 / ( dDist1 + abs( dDist2))) ; // se secondo esterno, devo spostare fine else if ( dDist2 > EPS_SMALL && ( -dDist1 - dHeight) > -100 * EPS_SMALL) ptP2 = Media( ptP2, ptP1, dDist2 / ( dDist2 + abs( dDist1))) ; } return true ; } //---------------------------------------------------------------------------- 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 ; // assegno angolo di fianco di default double dAngDef = dqFce[nStartInd].dAng ; // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return nullptr ; // recupero le entità free contour int nEnt = -1 ; for ( size_t i = nStartInd + 1 ; i < dqFce.size() ; ++ i) { // se retta if ( dqFce[i].nType == FreeContourEnt::LINE) { // se punti non coincidenti if ( ! AreSamePointApprox( dqFce[i-1].ptP, dqFce[i].ptP)) { // 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 ; ++ nEnt ; // imposto eventuale angolo di fianco (intero equivalente a millesimi di grado) double dAng = ( abs( dqFce[i].dAng - FC_SIDEANG_NONE) < EPS_ANG_SMALL ? dAngDef : dqFce[i].dAng) ; pCrvCompo->SetCurveTempProp( nEnt, int( 1000 * dAng)) ; } } // 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 ; ++ nEnt ; // imposto eventuale angolo di fianco (intero equivalente a millesimi di grado) double dAng = ( abs( dqFce[i].dAng - FC_SIDEANG_NONE) < EPS_ANG_SMALL ? dAngDef : dqFce[i].dAng) ; pCrvCompo->SetCurveTempProp( nEnt, int( 1000 * dAng)) ; } // altrimenti curva terminata else break ; } // imposto versore estrusione pCrvCompo->SetExtrusion( Z_AX) ; return Release( pCrvCompo) ; } //--------------------------------------------------------------------------- static ICurveComposite* GetDirectrixOfOneLoop( const PolyLine& PL, const Vector3d& vtExtr) { PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL)) return nullptr ; // cerco l'estremo più basso e lo imposto come inizio e inoltre calcolo quota massima double dU = 0 ; double dUmin = 0 ; double dZmin = INFINITO ; double dZmax = -INFINITO ; Point3d ptP ; while ( pCompo->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP)) { double dZ = ( ptP - ORIG) * vtExtr ; if ( dZ < dZmin) { dZmin = dZ ; dUmin = dU ; } if ( dZ > dZmax) dZmax = dZ ; dU += 1 ; } if ( dUmin != 0) pCompo->ChangeStartPoint( dUmin) ; // elimino curve agli estremi sotto la quota massima while ( pCompo->GetStartPoint( ptP) && ( ptP - ORIG) * vtExtr < dZmax - 100 * EPS_SMALL) delete( pCompo->RemoveFirstOrLastCurve( false)) ; while ( pCompo->GetEndPoint( ptP) && ( ptP - ORIG) * vtExtr < dZmax - 100 * EPS_SMALL) delete( pCompo->RemoveFirstOrLastCurve( true)) ; if ( pCompo->GetCurveCount() == 0) return nullptr ; // inverto la curva (per avere il materiale a destra) pCompo->Invert() ; // restituisco la curva return Release( pCompo) ; } //--------------------------------------------------------------------------- ICurve* BtlGeom::GetDirectrixOfRuledSurf( const ISurfTriMesh* pStm, const Vector3d& vtExtr) { // recupero la curva di contorno (loop) POLYLINEVECTOR vPL ; if ( ! pStm->GetLoops( vPL) || vPL.empty()) return nullptr ; // recupero la curva del primo loop PtrOwner pCompo( GetDirectrixOfOneLoop( vPL[0], vtExtr)) ; if ( IsNull( pCompo)) return nullptr ; // ciclo su eventuali loop successivi for ( int i = 1 ; i < int( vPL.size()) ; ++ i) { // recupero la curva PtrOwner pCrv( GetDirectrixOfOneLoop( vPL[i], vtExtr)) ; if ( IsNull( pCrv)) continue ; // verifico se precede o segue la curva principale Point3d ptSta1 ; pCompo->GetStartPoint( ptSta1) ; Point3d ptEnd1 ; pCompo->GetEndPoint( ptEnd1) ; Point3d ptSta2 ; pCrv->GetStartPoint( ptSta2) ; Point3d ptEnd2 ; pCrv->GetEndPoint( ptEnd2) ; double dDistE1S2 = Dist( ptEnd1, ptSta2) ; double dDistE2S1 = Dist( ptEnd2, ptSta1) ; // accodo le due curve di conseguenza if ( dDistE1S2 <= dDistE2S1) { if ( dDistE1S2 > 10 * EPS_SMALL) pCompo->AddLine( ptSta2, true) ; pCompo->AddCurve( Release( pCrv), true, 10 * EPS_SMALL) ; } else { if ( dDistE2S1 > 10 * EPS_SMALL) pCompo->AddLine( ptEnd2, false) ; pCompo->AddCurve( Release( pCrv), false, 10 * EPS_SMALL) ; } } // restituisco la curva return Release( pCompo) ; } //--------------------------------------------------------------------------- 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) ; m_pGDB->SetInfo( nId, IKEY_DES, sDes) ; m_pGDB->SetInfo( nId, IKEY_PRID, nProcId) ; return true ; } //--------------------------------------------------------------------------- bool BtlGeom::SetParams( int nId, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { if ( nId == GDB_ID_NULL) return false ; // elenco dei parametri int nNumPar = min( int( vnDPar.size()), int( vdPar.size())) ; for ( int i = 0 ; i < nNumPar ; ++ i) { string sKey = IKEY_PAR + ToString( abs( vnDPar[i]), 2) ; m_pGDB->SetInfo( nId, sKey, vdPar[i]) ; } // elenco degli eventuali attributi utente return SetUserAttributes( nId, vsUAtt) ; } //--------------------------------------------------------------------------- bool BtlGeom::SetUserAttributes( int nId, const STRVECTOR& vsUAtt) { if ( nId == GDB_ID_NULL) return false ; // elenco degli eventuali attributi utente for ( const auto& sUAtt : vsUAtt) { string sKey, sVal ; if ( ReadUserAttribute( sUAtt, sKey, sVal)) { // salvo nelle note m_pGDB->SetInfo( nId, sKey, sVal) ; // se disabilitazione, cambio colore if ( sKey == IKEY_DO && sVal == "0") { SetProcessColor( nId, false) ; } } } return true ; } //--------------------------------------------------------------------------- bool BtlGeom::SetProcessColor( int nId, bool bEnable) { if ( nId == GDB_ID_NULL) return false ; // determino il nuovo colore Color cNewCol = ( bEnable ? m_ProcsCol : m_ProcsOffCol) ; int nAlpha ; if ( m_pGDB->GetInfo( nId, IKEY_COL_A, nAlpha)) { if ( bEnable || nAlpha < m_ProcsOffCol.GetIntAlpha()) cNewCol.SetAlpha( nAlpha) ; } // assegno il nuovo colore al processo m_pGDB->SetMaterial( nId, cNewCol) ; // se ci sono geometrie ausiliarie, assegno il nuovo colore anche a queste INTVECTOR vAux ; if ( m_pGDB->GetInfo( nId, IKEY_AUXID, vAux) && ! vAux.empty()) { for ( auto nAux : vAux) m_pGDB->SetMaterial( nId + nAux, cNewCol) ; } return true ; } //--------------------------------------------------------------------------- bool BtlGeom::SetMainAdjId( int nMainId, const INTVECTOR& vnAdjId) { if ( nMainId == GDB_ID_NULL) return false ; // inserisco chiave con spiazzamento Id di geometrie aggiuntive string sInfo ; for ( auto nAdjId : vnAdjId) { if ( nAdjId != GDB_ID_NULL) { if ( nAdjId >= nMainId) sInfo += "+" + ToString( nAdjId - nMainId) + "," ; else sInfo += ToString( nAdjId - nMainId) + "," ; } } if ( ! sInfo.empty()) sInfo.pop_back() ; m_pGDB->SetInfo( nMainId, IKEY_ADJID, sInfo) ; // inserisco rimando al main in tutti gli aggiuntivi for ( auto nAdjId : vnAdjId) { if ( nAdjId != GDB_ID_NULL) { string sAdjInfo ; if ( nMainId >= nAdjId) sAdjInfo += "+" + ToString( nMainId - nAdjId) ; else sAdjInfo += ToString( nMainId - nAdjId) ; m_pGDB->SetInfo( nAdjId, IKEY_MAINID, sAdjInfo) ; } } // copio eventuali info con TASKID CopyTaskId( nMainId, vnAdjId) ; // se feature disabilitata, cambio stato e colore anche alle geometrie aggiuntive int nDO = 1 ; if ( ! vnAdjId.empty() && m_pGDB->GetInfo( nMainId, IKEY_DO, nDO) && nDO == 0) { for ( auto nAdjId : vnAdjId) { m_pGDB->SetInfo( nAdjId, IKEY_DO, 0) ; SetProcessColor( nAdjId, false) ; } } return true ; } //--------------------------------------------------------------------------- bool BtlGeom::SetAuxId( int nId, const INTVECTOR& vnAuxId) { if ( nId == GDB_ID_NULL) return false ; // inserisco chiave con spiazzamento Id di geometrie ausiliarie string sInfo ; for ( auto nAuxId : vnAuxId) { if ( nAuxId != GDB_ID_NULL) { if ( nAuxId >= nId) sInfo += "+" + ToString( nAuxId - nId) + "," ; else sInfo += ToString( nAuxId - nId) + "," ; } } if ( ! sInfo.empty()) sInfo.pop_back() ; m_pGDB->SetInfo( nId, IKEY_AUXID, sInfo) ; // copio eventuali info con TASKID CopyTaskId( nId, vnAuxId) ; // se feature disabilitata, cambio colore anche alle geometrie ausiliarie int nDO = 1 ; if ( ! vnAuxId.empty() && m_pGDB->GetInfo( nId, IKEY_DO, nDO) && nDO == 0) { // determino il nuovo colore Color cNewCol = m_ProcsOffCol ; int nAlpha ; if ( m_pGDB->GetInfo( nId, IKEY_COL_A, nAlpha)) { if ( nAlpha < m_ProcsOffCol.GetIntAlpha()) cNewCol.SetAlpha( nAlpha) ; } // assegno il nuovo colore alle geometrie ausiliarie for ( auto nAuxId : vnAuxId) m_pGDB->SetMaterial( nAuxId, cNewCol) ; } return true ; } //--------------------------------------------------------------------------- bool BtlGeom::SetDrillEnds( int nId, int nStartFace, int nEndFace) { if ( nId == GDB_ID_NULL) return false ; // inserisco chiavi con indice facce di inizio/fine foro m_pGDB->SetInfo( nId, IKEY_START_FACE, nStartFace) ; m_pGDB->SetInfo( nId, IKEY_END_FACE, nEndFace) ; return true ; } //--------------------------------------------------------------------------- bool BtlGeom::CopyTaskId( int nId, const INTVECTOR& vnAuxId) { // Recupero eventuale info TaskId dalla prima entità int nTaskId ; if ( ! m_pGDB->GetInfo( nId, IKEY_TASKID, nTaskId)) return true ; // La riporto nelle altre entità for ( auto nAuxId : vnAuxId) { m_pGDB->SetInfo( nAuxId, IKEY_TASKID, nTaskId) ; } return true ; } //--------------------------------------------------------------------------- bool BtlGeom::GetUserParam( const STRVECTOR& vsUAtt, const string& sKey, double& dVal) { for ( const auto& sUAtt : vsUAtt) { string sCurrKey, sVal ; if ( ReadUserAttribute( sUAtt, sCurrKey, sVal) && sCurrKey == sKey) return FromString( sVal, dVal) ; } return false ; } //--------------------------------------------------------------------------- bool BtlGeom::InsertEmptySurface( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const Frame3d& frRef, const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { // creo la superficie vuota PtrOwner pStm( CreateSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->AdjustTopology()) return false ; // la inserisco nel DB geometrico int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ; if ( nId == GDB_ID_NULL) return false ; // aggiungo nome e info con tipo SetNameAndInfo( nId, nGroup, nProc, nSide, sDes, nProcId) ; // riferimento if ( ! IsGlobFrame( frRef)) m_pGDB->SetInfo( nId, IKEY_FRAME, frRef) ; // aggiungo parametri SetParams( nId, vnDPar, vdPar, vsUAtt) ; m_nProcId = nId ; return true ; } //--------------------------------------------------------------------------- bool BtlGeom::AdjustPointForPlaneNearBoxVertex( Point3d& ptP, const Vector3d& vtN, int nSide) { // Piano Plane3d plPlane ; if ( ! plPlane.Set( ptP, vtN)) return false ; Frame3d frRef = GetSideFrame( nSide) ; plPlane.ToGlob( frRef) ; // Vertici del box PNTVECTOR vBoxVert = { Point3d( 0, 0, 0), Point3d( 0, 0, m_vtDim.z), Point3d( m_vtDim.x, 0, 0), Point3d( m_vtDim.x, 0, m_vtDim.z), Point3d( 0, m_vtDim.y, 0), Point3d( 0, m_vtDim.y, m_vtDim.z), Point3d( m_vtDim.x, m_vtDim.y, 0), Point3d( m_vtDim.x, m_vtDim.y, m_vtDim.z)} ; for ( const auto& ptV : vBoxVert) { double dDist = DistPointPlane( ptV, plPlane) ; if ( abs( dDist) < 10 * EPS_SMALL) { ptP += dDist * vtN ; break ; } } return true ; } //-------------------------------------------------------------------------------------------------------------------------- //----------------------------------- FUNZIONI PER PARAMETRI DA BTLX ------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool BtlGeom::AddTenonBTLX( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { double dStartX = vdPar[0] ; double dStartY = vdPar[1] ; double dStartDepth = vdPar[10] ; double dLength = vdPar[11] ; // versore normale alla faccia di taglio Vector3d vtN = FromSpherical( 1, 180 + vdPar[5], vdPar[4] - 90) ; if ( nGroup == 1) vtN.Mirror( X_AX) ; // sistema di riferimento sul piano di taglio centrato nello start point del tenone Frame3d frTen ; frTen.Set( Point3d( dStartX, dStartY, - dStartDepth), vtN, Z_AX ^ vtN) ; frTen.Rotate( Point3d( dStartX, dStartY, - dStartDepth), vtN, ( nGroup != 1 ? 90 - vdPar[6] : vdPar[6] - 90)) ; frTen.ToGlob( GetSideFrame( nSide)) ; double dThick = GetSideHeight( nSide) ; double dCosA = frTen.VersY() * GetSideVersN( nSide) ; double dL = dThick / dCosA ; // lunghezza lato faccia taglio vdPar[10] = dStartDepth / dCosA ; // P14 vdPar[11] = dL - vdPar[10] - dLength ; // P15 Point3d FacePoint( 0, vdPar[10], 0) ; // coord in frTen FacePoint.LocToLoc( frTen, GetSideFrame( nSide)) ; vdPar[0] = FacePoint.x ; // P01 vdPar[1] = FacePoint.y ; // P02 return AddTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; } //---------------------------------------------------------------------------- bool BtlGeom::AddDovetailTenonBTLX( int nGroup, int nProc, int nSide, const string& sDes, int nProcId, const INTVECTOR& vnDPar, DBLVECTOR& vdPar, const STRVECTOR& vsUAtt) { double dStartX = vdPar[0] ; double dStartY = vdPar[1] ; double dStartDepth = vdPar[10] ; double dLength = vdPar[11] ; // versore normale alla faccia di taglio Vector3d vtN = FromSpherical( 1, 180 + vdPar[4], vdPar[3] - 90) ; if ( nGroup == 1) vtN.Mirror( X_AX) ; // sistema di riferimento sul piano di taglio centrato nello start point del tenone Frame3d frTen ; frTen.Set( Point3d( dStartX, dStartY, - dStartDepth), vtN, Z_AX ^ vtN) ; frTen.Rotate( Point3d( dStartX, dStartY, - dStartDepth), vtN, ( nGroup != 1 ? 90 - vdPar[5] : vdPar[5] - 90)) ; frTen.ToGlob( GetSideFrame( nSide)) ; double dThick = GetSideHeight( nSide) ; double dCosA = frTen.VersY() * GetSideVersN( nSide) ; double dL = dThick / dCosA ; // lunghezza lato faccia taglio vdPar[10] = dStartDepth / dCosA ; // P14 vdPar[11] = dL - vdPar[10] - dLength ; // P15 Point3d FacePoint( 0, vdPar[10], 0) ; // coord in frTen FacePoint.LocToLoc( frTen, GetSideFrame( nSide)) ; vdPar[0] = FacePoint.x ; // P01 vdPar[1] = FacePoint.y ; // P02 return AddDovetailTenon( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt) ; }