Files
EgtExchange/BtlGeomProc.cpp
Dario Sassi 91d1260d8a EgtExchange 3.1e2 :
- in import BTL aggiunta gestione Tenone Coda di Rondine non limitato dal lato dell'arrotondamento (P04=1).
2026-05-13 11:09:23 +02:00

9189 lines
395 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2024
//----------------------------------------------------------------------------
// File : BtlGeomProc.cpp Data : 28.02.24 Versione : 2.6b4
// 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).
// 22.02.24 DS Agg. import Sphere (3/4-107-X).
// 28.02.24 DS Agg. gestione Klingschrot in feature TyroleanDovetail.
//
//----------------------------------------------------------------------------
//--------------------------- 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/EGkStmStandard.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkSbzFromCurves.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkDistLineLine.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EXeExecutor.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
#include "/EgtDev/Include/EGnFileUtils.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGnLuaAux.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
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 sfera
if ( IS_SPHERE( nGroup, nProc)) {
vnDPar.reserve( 6) ; vdPar.reserve( 6) ;
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.5 * GetSideHeight( nSide)) ;
vnDPar.emplace_back( 11) ; vdPar.emplace_back( 0.5 * GetSideWidth( nSide)) ;
vnDPar.emplace_back( 12) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 13) ; vdPar.emplace_back( -1) ;
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( 25) ; vdPar.reserve( 25) ;
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( 5) ; 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( 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) ;
vnDPar.emplace_back( 16) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 17) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 18) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 19) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 20) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 21) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 22) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 23) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 24) ; vdPar.emplace_back( 0) ;
vnDPar.emplace_back( 25) ; 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 sfera
if ( IS_SPHERE( nGroup, nProc))
return AddSphere( 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<ISurfTriMesh> 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<ICurve> 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<ICurve> 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<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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<ICurve> 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}) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<IGeoVector3d> pGvt( CreateGeoVector3d()) ;
if ( IsNull( pGvt) || ! pGvt->Set( vtDir, ptCen))
return false ;
// creo la trimesh con questo contorno
PtrOwner<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
return false ;
pCompo->SetExtrusion( frMort.VersZ()) ;
// definisco la superficie di taglio
PtrOwner<ISurfTriMesh> pCut ;
// creo la regione del contorno esterno
PtrOwner<ICurveComposite> pExt( CreateCurveComposite()) ;
if ( IsNull( pExt))
return false ;
if ( pExt->FromPolyLine( plyCut.GetPolyLine())) {
SurfFlatRegionByContours SfrExt ;
SfrExt.AddCurve( Release( pExt)) ;
PtrOwner<ISurfFlatRegion> pReg( SfrExt.GetSurf()) ;
if ( IsNull( pReg))
return false ;
// creo la regione della mortasa
SurfFlatRegionByContours SfrMrt ;
SfrMrt.AddCurve( pCompo->Clone()) ;
PtrOwner<ISurfFlatRegion> 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() ;
}
// Facce della mortasa
Polygon3d plyFaceF ;
if ( ! CreatePolygonInBox( GetToGlob( Point3d( 0, 0, -dMortD), frMort), frMort.VersZ(), BTL_SIDE_NONE, plyFaceF))
return false ;
Polygon3d plyFace1 ;
if ( ! CreatePolygonInBox( GetToGlob( Point3d( -dMortHW, 0, 0), frMort), frMort.VersX(), BTL_SIDE_NONE, plyFace1))
return false ;
Polygon3d plyFace2 ;
if ( ! CreatePolygonInBox( GetToGlob( Point3d( 0, -dMortHL, 0), frMort), frMort.VersY(), BTL_SIDE_NONE, plyFace2))
return false ;
Polygon3d plyFace3 ;
if ( ! CreatePolygonInBox( GetToGlob( Point3d( dMortHW, 0, 0), frMort), -frMort.VersX(), BTL_SIDE_NONE, plyFace3))
return false ;
Polygon3d plyFace4 ;
if ( ! CreatePolygonInBox( GetToGlob( Point3d( 0, dMortHL, 0), frMort), -frMort.VersY(), BTL_SIDE_NONE, 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<ISurfTriMesh> 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) ;
// la limito con il piano di taglio (un poco pi alto, per evitare problemi con solidi)
Plane3d plCut ;
plCut.Set( GetToGlob( Point3d( 0, 0, 100 * EPS_SMALL), frMort), frMort.VersZ()) ;
pStm->Cut( plCut, false) ;
// 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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}) ;
}
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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<ISurfTriMesh> 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 (il primo una correzione di un errore di Dietrich's)
if ( nFlag < 0 || nFlag >= 63) {
// messaggio di warning in log
string sOut = " Warning : All Faces Open On Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) +
") on line " + ToString( m_nBtlLine) ;
LOG_WARN( GetEExLogger(), sOut.c_str())
nFlag = 0 ;
}
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 se completamente fuori dalla trave, nel qual caso inserisco superficie vuota
bool bOut = (( plyStart.IsValid() && GetDistanceBeamPlane( plyStart.GetPlane()) < -EPS_ZERO) ||
( plyEnd.IsValid() && GetDistanceBeamPlane( plyEnd.GetPlane()) < -EPS_ZERO) ||
( plyFront.IsValid() && GetDistanceBeamPlane( plyFront.GetPlane()) < -EPS_ZERO) ||
( plyBack.IsValid() && GetDistanceBeamPlane( plyBack.GetPlane()) < -EPS_ZERO) ||
( plyTop.IsValid() && GetDistanceBeamPlane( plyTop.GetPlane()) < -EPS_ZERO) ||
( plyBottom.IsValid() && GetDistanceBeamPlane( plyBottom.GetPlane()) < -EPS_ZERO)) ;
if ( bOut) {
// 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 ;
}
// 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<ISurfTriMesh> 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) ;
// se superficie divisa in pi parti, elimino quelle troppo piccole
if ( pStm->GetPartCount() > 1) {
// elimino le parti di area non significativa
for ( int i = 0 ; i < pStm->GetPartCount() ;) {
double dArea ;
if ( ! pStm->GetPartArea( i, dArea) || dArea < FACE_DETACHED_MIN_AREA)
pStm->RemovePart( i) ;
else
++ i ;
}
}
bool bIsSplit = ( pStm->GetPartCount() > 1) ;
// 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) ;
// se pi parti disconnesse
if ( bIsSplit) {
// disabilito la feature
m_pGDB->SetInfo( nId, IKEY_DO, 0) ;
SetProcessColor( nId, false) ;
// messaggio di warning in log
string sOut = " Warning : Split Process (" + ToString( nGroup) + "-" + ToString( nProc, 3) + "-" + ToString( nSide) +
") on line " + ToString( m_nBtlLine) ;
LOG_WARN( GetEExLogger(), sOut.c_str())
}
// 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<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurveArc> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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 = - X_AX * GetSideWidth( nSide) / vtN1.x ;
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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ICurveArc> 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<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> 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] + ( bHouse ? 100 * EPS_SMALL : 0) ; // 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<ICurveComposite> pCrvTen( CreateCurveComposite()) ;
if ( IsNull( pCrvTen) || ! pCrvTen->FromPolyArc( PA))
return false ;
pCrvTen->SetExtrusion( Z_AX) ;
pCrvTen->ToGlob( frTen) ;
// lo approssimo con una spezzata
PtrOwner<ICurveComposite> 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<ICurveComposite> pExt( CreateCurveComposite()) ;
if ( IsNull( pExt) || ! pExt->FromPolyLine( plyCut.GetPolyLine()))
return false ;
SurfFlatRegionByContours SfrExt ;
SfrExt.AddCurve( Release( pExt)) ;
PtrOwner<ISurfFlatRegion> pReg( SfrExt.GetSurf()) ;
if ( IsNull( pReg))
return false ;
// creo la regione del tenone
SurfFlatRegionByContours SfrTen ;
SfrTen.AddCurve( pCompo->Clone()) ;
PtrOwner<ISurfFlatRegion> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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] ; // 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
double dAngle = Clamp( vdPar[4], -180.0, 180.0) ; // P06
double dSideIncl = Clamp( vdPar[6], 0.1, 179.9) ; // P08
double dFrontIncl = Clamp( vdPar[13], 0.1, 179.9) ; // P16
double dFillet = vdPar[7] ; // P10
double dMortD = vdPar[8] ; // P11
double dMortW = vdPar[9] ; // P12
double dStrutAng = Clamp( vdPar[5], 0.1, 179.9) ; // P07
double dMortM1 = vdPar[11] ; // P14
double dMortM2 = vdPar[12] ; // P15
double dMortL = Clamp( vdPar[10] / sin( dStrutAng * DEGTORAD) - dMortM1 - dMortM2, 1., 99999.) ; // P13
Point3d ptP( dStartX, dStartY, dStartZ) ;
// calcolo riferimento della faccia di fondo
Frame3d frMort ;
if ( nGroup != 3) {
frMort.Set( ORIG, Z_AX, Y_AX) ;
frMort.Rotate( ORIG, -X_AX, dSideIncl - 90) ;
frMort.Rotate( ORIG, -Y_AX, dFrontIncl - 90) ;
frMort.Rotate( ORIG, Z_AX, dAngle) ;
}
else {
frMort.Set( ORIG, Z_AX, -Y_AX) ;
frMort.Rotate( ORIG, X_AX, dSideIncl - 90) ;
frMort.Rotate( ORIG, Y_AX, dFrontIncl - 90) ;
frMort.Rotate( ORIG, -Z_AX, dAngle) ;
}
double dCoeffZ = frMort.VersZ().z ;
frMort.ChangeOrig( ptP - dMortD * frMort.VersZ()) ;
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<ICurveComposite> pCrvMort( CreateCurveComposite()) ;
if ( IsNull( pCrvMort) || ! pCrvMort->FromPolyArc( PA))
return false ;
pCrvMort->SetExtrusion( Z_AX) ;
pCrvMort->ToGlob( frMort) ;
// lo approssimo con una spezzata
PtrOwner<ICurveComposite> 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<ISurfTriMesh> 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 / dCoeffZ ;
if ( abs( ANG_RIGHT - dFrontIncl) > EPS_ANG_SMALL || abs( ANG_RIGHT - dSideIncl) > EPS_ANG_SMALL)
dExtr += 50.0 ;
PtrOwner<ISurfTriMesh> 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<ICurve> 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}) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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<ICurveComposite> pCrvTen( CreateCurveComposite()) ;
if ( IsNull( pCrvTen) || ! pCrvTen->FromPolyArc( PA))
return false ;
pCrvTen->SetExtrusion( Z_AX) ;
pCrvTen->ToGlob( frMort) ;
// lo approssimo con una spezzata
PtrOwner<ICurveComposite> 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<ISurfTriMesh> pStmCut ;
// creo la regione del contorno esterno
PtrOwner<ICurveComposite> pExt( CreateCurveComposite()) ;
if ( IsNull( pExt))
return false ;
if ( pExt->FromPolyLine( plyCut.GetPolyLine())) {
SurfFlatRegionByContours SfrExt ;
SfrExt.AddCurve( Release( pExt)) ;
PtrOwner<ISurfFlatRegion> pReg( SfrExt.GetSurf()) ;
if ( IsNull( pReg))
return false ;
// creo la regione della mortasa
SurfFlatRegionByContours SfrMrt ;
SfrMrt.AddCurve( pCompo->Clone()) ;
PtrOwner<ISurfFlatRegion> 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<ISurfTriMesh> pStmCap( CreateSurfTriMesh()) ;
if ( IsNull( pStmCap) || ! pStmCap->CreateByPointCurve( ptCen, PL))
return false ;
pStmCap->Translate( - frMort.VersZ() * dMortD) ;
// creo la superficie trimesh della mortasa
PtrOwner<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurve> 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 ;
}
// se di tipo illimitato sull'arrotondamento
if ( nFlag == 1) {
dTenW += 2 * dFillet ;
dFillet = 0 ;
dTenM2 = -DTTEN_EXTRA_LEN ;
}
// 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 ;
if ( dY3 > dY2)
PB.AddUPoint( 3, Point3d( dX3, dY3, 0), 0) ;
PolyArc PA = PB ;
PA.Mirror( ORIG, X_AX) ;
PA.Invert( true) ;
PA.Join( PB, 3) ;
PtrOwner<ICurveComposite> pCrvTen( CreateCurveComposite()) ;
if ( IsNull( pCrvTen) || ! pCrvTen->FromPolyArc( PA))
return false ;
pCrvTen->SetExtrusion( Z_AX) ;
pCrvTen->ToGlob( frTen) ;
// lo approssimo con una spezzata
PtrOwner<ICurveComposite> 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<ICurveComposite> 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<ICurveComposite> pExt( CreateCurveComposite()) ;
if ( IsNull( pExt) || ! pExt->FromPolyLine( plyCut.GetPolyLine()))
return false ;
SurfFlatRegionByContours SfrExt ;
SfrExt.AddCurve( Release( pExt)) ;
PtrOwner<ISurfFlatRegion> pReg( SfrExt.GetSurf()) ;
if ( IsNull( pReg))
return false ;
// creo la regione del tenone
SurfFlatRegionByContours SfrTen ;
SfrTen.AddCurve( pCompo->Clone()) ;
PtrOwner<ISurfFlatRegion> 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<ISurfTriMesh> pStm ;
if ( pReg->GetAuxSurf() != nullptr) {
pStm.Set( pReg->GetAuxSurf()->Clone()) ;
if ( IsNull( pStm))
return false ;
}
// Creo la superficie trimesh del tenone
PtrOwner<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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 = dMortL ;
if ( dMortA > EPS_ANG_SMALL)
dExtraLen = Clamp( dOffs / sin( dMortA * DEGTORAD), MIN_DTMORT_POCKET, dMortL) ;
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<ICurveComposite> 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<ICurveComposite> 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<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurve> 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<ICurve> 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}) ;
// eseguo trim con outline (se richiesto)
TrimProcessWithOutline( nId) ;
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 = dMortL ;
if ( dMortA > EPS_ANG_SMALL)
dExtraLen = Clamp( dOffs / sin( dMortA * DEGTORAD), MIN_DTMORT_POCKET, dMortL) ;
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<ICurveComposite> pCrvTop( CreateCurveComposite()) ;
if ( IsNull( pCrvTop) || ! pCrvTop->FromPolyArc( PA))
return false ;
pCrvTop->SetExtrusion( Z_AX) ;
// Creo il contorno basso della mortasa
PtrOwner<ICurveComposite> 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<ICurveComposite> 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<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( ! pCompo->FromPolyLine( PL2))
return false ;
pCompo->Close() ;
pCompo->SetExtrusion( frMort.VersZ()) ;
// Creo la regione del contorno esterno
PtrOwner<ICurveComposite> 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<ISurfFlatRegion> pReg( SfrExt.GetSurf()) ;
if ( IsNull( pReg))
return false ;
// Creo la regione della mortasa
SurfFlatRegionByContours SfrMort ;
SfrMort.AddCurve( Release( pCompo)) ;
PtrOwner<ISurfFlatRegion> 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<ISurfTriMesh> pStmCut ;
if ( pReg->GetAuxSurf()) {
pStmCut.Set( pReg->GetAuxSurf()->Clone()) ;
if ( IsNull( pStmCut))
return false ;
}
// Creo la superficie trimesh della mortasa
PtrOwner<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurve> 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<ICurve> 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<ICurveLine> 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<ICurveLine> 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<ICurveLine> 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<ICurveLine> pLine( CreateCurveLine()) ;
if ( IsNull( pLine))
return false ;
// assegno i dati
if ( ! pLine->SetPVL( ptP, vtD, dLen))
return false ;
// la inserisco nella composita
PtrOwner<ICurveComposite> 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<IExtText> 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 = ETXT_IPMC ;
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
int nChar = ssize( sPar) ;
for ( int 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<IExtText> 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<ISurfTriMesh> 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<ICurve> 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<ISurfTriMesh> 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<ICurveComposite> 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<ISurfTriMesh> 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<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurveComposite> 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<ISurfTriMesh> 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<ICurveComposite> 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<ISurfTriMesh> 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<ICurveBezier> 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<ICurveComposite> 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<ISurfTriMesh> 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<ICurveComposite> 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<ISurfTriMesh> 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<ICurve> pCrv ;
if ( ! pCrv.Set( GetArc3P( ptP1, ptP2, ptP3, false)))
return false ;
PtrOwner<ICurveComposite> 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<ISurfTriMesh> 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::AddSphere( 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 dStartY = vdPar[1] ; // P02
double dStartZ = -vdPar[2] ; // P03
double dRadius = Clamp( vdPar[3], 0., 50000.) ; // P11
double dOffset = Clamp( vdPar[4], 0., 2 * dRadius) ; // P12
double dLength = Clamp( ( vdPar[5] < 0 ? dRadius : vdPar[5]), 10 * EPS_SMALL, 2 * dRadius) ; // P13
// costruisco la curva del profilo
double dCenX = dStartX + ( nGroup == 4 ? dRadius : -dRadius) ;
Point3d ptCen( dCenX, dStartY, dStartZ) ;
double dIniDeltaX = Clamp( ( nGroup == 4 ? dRadius - dOffset : dOffset + dLength - dRadius), -dRadius, dRadius) ;
double dIniDeltaY = sqrt( max( dRadius * dRadius - dIniDeltaX * dIniDeltaX, 0.)) ;
Point3d ptIni( dCenX - dIniDeltaX, dStartY + dIniDeltaY, dStartZ) ;
double dFinDeltaX = Clamp( ( nGroup == 4 ? dOffset + dLength - dRadius : dRadius - dOffset), -dRadius, dRadius) ;
double dFinDeltaY = sqrt( max( dRadius * dRadius - dFinDeltaX * dFinDeltaX, 0.)) ;
Point3d ptFin( dCenX + dFinDeltaX, dStartY + dFinDeltaY, dStartZ) ;
PtrOwner<ICurve> pCrv ;
if ( ! pCrv.Set( GetArc2PCN( ptIni, ptFin, ptCen, Z_AX)))
return false ;
PtrOwner<ICurveComposite> pCrvCo( CreateCurveComposite()) ;
if ( IsNull( pCrvCo) || ! pCrvCo->AddCurve( Release( pCrv)))
return false ;
// aggiungo linea iniziale e finale (se serve)
double dLen = GetSideWidth( nSide) + GetSideHeight( nSide) ;
Point3d ptStart ; pCrvCo->GetStartPoint( ptStart) ;
Vector3d vtStart ; pCrvCo->GetStartDir( vtStart) ; vtStart.Rotate( Z_AX, 90) ;
if ( abs( vtStart.y) > EPS_SMALL) {
double dLs = dLen / abs( vtStart.y) ;
pCrvCo->AddLine( ptStart + vtStart * dLs, false) ;
}
Point3d ptEnd ; pCrvCo->GetEndPoint( ptEnd) ;
Vector3d vtEnd ; pCrvCo->GetEndDir( vtEnd) ; vtEnd.Rotate( Z_AX, 90) ;
if ( abs( vtEnd.y) > EPS_SMALL) {
double dLe = dLen / abs( vtEnd.y) ;
pCrvCo->AddLine( ptEnd + vtEnd * dLe) ;
}
// sistemo per riferimento faccia
Frame3d frRef = GetSideFrame( nSide) ;
ptCen.ToGlob( frRef) ;
pCrvCo->ToGlob( frRef) ;
// creo la superficie di rivoluzione attorno all'asse della trave
const double ANG_ROT_STEP = ( dRadius > 49.99 ? 1 : 2) ;
PolyLine PL ;
pCrvCo->ApproxWithLines( CRV_LIN_FINE_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL) ;
PtrOwner<ISurfTriMesh> pStm( CreateSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->CreateByRevolution( PL, ptCen, X_AX, ANG_FULL, ANG_ROT_STEP))
return false ;
// eseguo trim con le facce della trave
TrimSurfTmWithBox( pStm) ;
// inserisco la superficie trimesh nel DB geometrico
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStm)) ;
// 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) ;
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<ISurfTriMesh> 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 = Clamp( lround( vdPar[3]), 0, 1) ; // 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 dRadius = Clamp( vdPar[10], 0., 50000.) ; // P12
double dArcLen = Clamp( vdPar[11], 0., 50000.) ; // P13
double dLength = Clamp( vdPar[13], 0., 50000.) ; // P15
int nFlag = Clamp( lround( vdPar[14]), 0, 2) ; // P16
// punto di riferimento
Point3d ptP( dPos, 0, -dDepth) ;
// direzioni di riferimento
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) ;
}
// offset
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<ISurfTriMesh> 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 di tipo standard
if ( dRadius < 10 * EPS_SMALL || dArcLen < 10 * EPS_SMALL) {
// faccia frontale
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 dTanHalfAng = tan( ( nInsPos == 0 ? ( 180 - dAngle) : dAngle) / 2 * DEGTORAD) ;
// 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 / dTanHalfAng ;
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<ISurfTriMesh> 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 / dTanHalfAng ;
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<ISurfTriMesh> 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) ;
}
}
// se di tipo Klingschrot
else if ( abs( dAngle - ANG_RIGHT) < EPS_ANG_SMALL && dRadius >= dArcLen) {
if ( dLength >= dArcLen && GetSideWidth( nSide) - dInside >= dArcLen) {
// posizione vertice di riferimento
Point3d ptV( dPos, 0, -dDepth + dHeight) ;
// altezza arco di profilo e guida
double dArcH = dRadius - sqrt( dRadius * dRadius - dArcLen * dArcLen) ;
// profilo
PtrOwner<ICurveComposite> pProfile( CreateCurveComposite()) ;
if ( IsNull( pProfile))
return false ;
const double EXTRA_LEN = 10 ;
pProfile->SetExtrusion( -Y_AX) ;
pProfile->AddPoint( Point3d( -EXTRA_LEN, 0, 0)) ;
pProfile->AddLine( Point3d( dLength - dArcLen, 0, 0)) ;
pProfile->AddArcTg( Point3d( dLength, 0, -dArcH)) ;
pProfile->TrimStartAtLen( EXTRA_LEN) ;
pProfile->Translate( ptV - ORIG) ;
// guida
PtrOwner<ICurveComposite> pGuide( CreateCurveComposite()) ;
if ( IsNull( pGuide))
return false ;
double dGuideLen = GetSideWidth( nSide) - dInside ;
pGuide->SetExtrusion( -X_AX) ;
pGuide->AddPoint( Point3d( 0, -EXTRA_LEN, 0)) ;
pGuide->AddLine( Point3d( 0, dGuideLen - dArcLen, 0)) ;
pGuide->AddArcTg( Point3d( 0, dGuideLen, dArcH)) ;
if ( dInside > 10 * EPS_SMALL) {
Vector3d vtEndDir ; pGuide->GetEndDir( vtEndDir) ;
double dCoeff = ( abs( vtEndDir.y) > EPS_SMALL ? 1 / abs( vtEndDir.y) : 2) ;
pGuide->AddLineTg( dInside * dCoeff) ;
}
pGuide->TrimStartAtLen( EXTRA_LEN) ;
pGuide->Translate( ptV - ORIG) ;
// creo la superficie ondulata
PtrOwner<ISurfTriMesh> pStm( GetSurfTriMeshTransSwept( pProfile, pGuide, false, 50 * EPS_SMALL)) ;
if ( IsNull( pStm))
return false ;
// copia della guida alla fine della sezione
PtrOwner<ICurveComposite> pGuide2( pGuide->Clone()) ;
if ( IsNull( pGuide2))
return false ;
pGuide2->Translate( Point3d( dLength, 0, -dArcH) - ORIG) ;
// creo la superficie piana
PtrOwner<ISurfTriMesh> pStm2( GetSurfTriMeshByExtrusion( pGuide2, Z_AX * GetSideHeight( nSide), false, 50 * EPS_SMALL)) ;
if ( IsNull( pStm2))
return false ;
pStm2->Invert() ;
// unisco le due superfici
if ( ! pStm->DoSewing( *pStm2))
return false ;
// sposto la guida in posizione adatta per lavorazione
pGuide->Translate( dLength * X_AX) ;
// eventuali inversioni per lato riferimento
if ( nInsPos == 0) {
Point3d ptMir( 0, GetSideWidth( nSide) / 2, 0) ;
pStm->Mirror( ptMir, Y_AX) ;
pGuide->Mirror( ptMir, Y_AX) ;
pGuide->Invert() ;
}
// eventuali inversioni per gruppo (testa/coda)
if ( nGroup == 1 || nGroup == 3) {
pStm->Mirror( ptV, X_AX) ;
pGuide->Mirror( ptV, X_AX) ;
pGuide->Invert() ;
}
// se prevista parte sopra, la inserisco
if ( nFlag == 0 || nFlag == 1) {
// copio la superficie di riferimento
PtrOwner<ISurfTriMesh> pStmT( pStm->Clone()) ;
if ( IsNull( pStmT))
return false ;
// porto nel riferimento trave
pStmT->ToGlob( GetSideFrame( nSide)) ;
// eseguo trim con le facce della trave
TrimSurfTmWithBox( pStmT) ;
// inserisco la superficie nel DB geometrico
int nStmTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmT)) ;
if ( nStmTId == GDB_ID_NULL)
return false ;
// copio la curva guida
PtrOwner<ICurveComposite> pGuideT( pGuide->Clone()) ;
// porto nel riferimento trave
pGuideT->ToGlob( GetSideFrame( nSide)) ;
// inserisco la curva nel DB geometrico
int nGuideTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pGuideT)) ;
if ( nGuideTId == GDB_ID_NULL)
return false ;
// nome e info con tipo
SetNameAndInfo( nStmTId, nGroup, nProc, nSide, sDes, nProcId) ;
// parametri
SetParams( nStmTId, vnDPar, vdPar, vsUAtt) ;
// se presenti, aggiungo identificativi di geometrie ausiliarie
SetAuxId( nStmTId, { nAuxId, nGuideTId}) ;
// salvo Id
vIds.emplace_back( nStmTId) ;
}
// se prevista parte sotto, la inserisco
if ( nFlag == 0 || nFlag == 2) {
// copio la superficie di riferimento
PtrOwner<ISurfTriMesh> pStmB( pStm->Clone()) ;
if ( IsNull( pStmB))
return false ;
// ne faccio il mirror
pStmB->Mirror( Point3d( 0, 0, -dDepth), Z_AX) ;
// porto nel riferimento trave
pStmB->ToGlob( GetSideFrame( nSide)) ;
// eseguo trim con le facce della trave
TrimSurfTmWithBox( pStmB) ;
// inserisco la superficie nel DB geometrico
int nStmBId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pStmB)) ;
if ( nStmBId == GDB_ID_NULL)
return false ;
// copio la curva guida
PtrOwner<ICurveComposite> pGuideB( pGuide->Clone()) ;
// ne faccio il mirror e invert
pGuideB->Mirror( Point3d( 0, 0, -dDepth), Z_AX) ;
pGuideB->Invert() ;
// porto nel riferimento trave
pGuideB->ToGlob( GetSideFrame( nSide)) ;
// inserisco la curva nel DB geometrico
int nGuideBId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, Release( pGuideB)) ;
if ( nGuideBId == GDB_ID_NULL)
return false ;
// nome e info con tipo
SetNameAndInfo( nStmBId, nGroup, nProc, nSide, sDes, nProcId) ;
// parametri
SetParams( nStmBId, vnDPar, vdPar, vsUAtt) ;
// se presenti, aggiungo identificativi di geometrie ausiliarie
SetAuxId( nStmBId, { nAuxId, nGuideBId}) ;
// salvo Id
vIds.emplace_back( nStmBId) ;
}
}
else {
if ( dLength < dArcLen) {
string sOut = " Klingschrot : Length (P15) less than Tool Length (P13)" ;
LOG_WARN( GetEExLogger(), sOut.c_str())
}
else {
string sOut = " Klingschrot : SideWidth (" + ToString( GetSideWidth( nSide), 1) +
") minus Inside (P02) less than Tool Length (P13)" ;
LOG_WARN( GetEExLogger(), sOut.c_str())
}
dInside = 0 ;
}
}
// altrimenti errore
else {
dInside = 0 ;
}
// 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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)
{
// recupero il codice identificativo
int nCode = 0 ;
FromString( sDes, nCode) ;
// se trovo il file lua corrispondente
string sBasePath = m_sBtlAuxDir + "/" + VARIANT_BASENAME + ToString( nCode, 2) ;
string sLuaPath = sBasePath + ".lua" ;
string sNgePath = sBasePath + ".nge" ;
if ( ExistsFile( sLuaPath))
return AddVariantLua( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt, sLuaPath) ;
else
return AddVariantNge( nGroup, nProc, nSide, sDes, nProcId, vnDPar, vdPar, vsUAtt, sNgePath) ;
}
//----------------------------------------------------------------------------
bool
BtlGeom::AddVariantLua( int nGroup, int nProc, int nSide, const string& sDes, int nProcId,
const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt, const string& sLuaPath)
{
// verifica dei parametri
if ( vdPar.size() < 25)
return false ;
// costanti
static const string EIB_VAR = "EIB" ; // tabella variabili locali per calcolo
static const string EVAR_GROUP = ".GROUP" ; // gruppo della feature
static const string EVAR_PROC = ".PROC" ; // processo della feature
static const string EVAR_SIDE = ".SIDE" ; // fianco di inserimento della feature
static const string EVAR_FACE = ".FACE" ; // faccia di inserimento della feature
static const string EVAR_FACE_L = ".FACE_L" ; // lunghezza della faccia di inserimento
static const string EVAR_FACE_W = ".FACE_W" ; // larghezza della faccia di inserimento
static const string EVAR_FACE_H = ".FACE_H" ; // spessore della trave perpendicolare alla faccia di inserimento
static const string EVAR_PARAM = ".P" ; // inizio parametro
static const string EVAR_ERR = ".ERR" ; // codice di errore
static const string EVAR_NGEFILE = ".NGEFILE" ; // path del file Nge in cui stata salvata la feature in posizione canonica
// creo e imposto contesto dedicato
int nOldCtx = ExeGetCurrentContext() ;
int nCtx = ExeInitContext() ;
// alcune determinazioni geometriche
Vector3d vtMove( vdPar[0], vdPar[1], -vdPar[2]) ; // P01, P02, P03
int nFace = nSide ;
if ( abs( vtMove.z) > EPS_SMALL && nGroup != 0)
nFace = ( nGroup == 3 ? BTL_SIDE_RIGHT : BTL_SIDE_LEFT) ;
double dFaceLen = GetSideLength( nFace) ;
double dFaceWth = GetSideWidth( nFace) ;
double dFaceHgt = GetSideHeight( nFace) ;
// imposto variabili da passare allo script
bool bOk = LuaCreateGlobTable( m_LuaMgr.GetLuaState(), EIB_VAR) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_GROUP, nGroup) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_PROC, nProc) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_SIDE, nSide) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_FACE, nFace) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_FACE_L, dFaceLen) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_FACE_W, dFaceWth) ;
bOk = bOk && LuaSetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_FACE_H, dFaceHgt) ;
for ( int i = 0 ; i < int( vnDPar.size()) && bOk ; ++ i) {
string sVarName = EIB_VAR + EVAR_PARAM + ToString( vnDPar[i], 2) ;
bOk = LuaSetGlobVar( m_LuaMgr.GetLuaState(), sVarName, vdPar[i]) ;
}
// eseguo
bOk = bOk && m_LuaMgr.ExecFile( sLuaPath) ;
// recupero valori
int nErr = 999 ;
bOk = bOk && LuaGetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_ERR, nErr) && nErr == 0 ;
string sNgePath ;
bOk = bOk && LuaGetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR + EVAR_NGEFILE, sNgePath) ;
// reset
bOk = LuaResetGlobVar( m_LuaMgr.GetLuaState(), EIB_VAR) && bOk ;
// ripristino contesto originale
ExeDeleteContext( nCtx) ;
ExeSetCurrentContext( nOldCtx) ;
// inserimento nuova geometria della featura
int nId = GDB_ID_NULL ;
INTVECTOR vAdjIds ;
INTVECTOR vAuxIds ;
// se tutto ok
if ( bOk) {
// inserimento di geometria custom
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( sNgePath, 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) ;
// eventuale aggiustamento dell'orientamento (gruppo 4 su faccia inizio, gruppo 3 su faccia fine)
if ( abs( vtMove.z) > EPS_SMALL && nGroup != 0) {
m_pGDB->Rotate( nEnt, ORIG, X_AX, ANG_RIGHT) ;
if ( nGroup == 4)
m_pGDB->Rotate( nEnt, ORIG, Z_AX, -ANG_RIGHT) ;
else
m_pGDB->Rotate( nEnt, ORIG, Z_AX, ANG_RIGHT) ;
}
// 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 ;
}
//----------------------------------------------------------------------------
bool
BtlGeom::AddVariantNge( int nGroup, int nProc, int nSide, const string& sDes, int nProcId,
const INTVECTOR& vnDPar, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt, const string& sNgePath)
{
// verifica dei parametri
if ( vdPar.size() < 12)
return false ;
// assegnazione parametri
Vector3d vtMove( vdPar[0], vdPar[1], -vdPar[2]) ; // P01, P02, P03
double dAngRot = Clamp( vdPar[5], -180.0, 180.0) ; // P06
double dXScale = Clamp( ( vdPar[9] < EPS_ZERO ? 1. : vdPar[9]), 0.01, 100.0) ; // P10
double dYScale = Clamp( ( vdPar[10] < EPS_ZERO ? 1. : vdPar[10]), 0.01, 100.0) ; // P11
double dZScale = Clamp( ( vdPar[11] < EPS_ZERO ? 1. : vdPar[11]), 0.01, 100.0) ; // P12
// inserimento di geometria custom
int nId = GDB_ID_NULL ;
INTVECTOR vAdjIds ;
INTVECTOR vAuxIds ;
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( sNgePath, 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) ;
// eventuale scalatura
if ( abs( dXScale - 1) > EPS_ZERO || abs( dYScale - 1) > EPS_ZERO || abs( dZScale -1) > EPS_ZERO)
m_pGDB->Scale( nEnt, Frame3d(), dXScale, dYScale, dZScale) ;
// eventuale rotazione
if ( abs( dAngRot) > EPS_ANG_ZERO)
m_pGDB->Rotate( nEnt, ORIG, Z_AX, dAngRot) ;
// eventuale aggiustamento dell'orientamento (gruppo 4 su faccia inizio, gruppo 3 su faccia fine)
if ( abs( vtMove.z) > EPS_SMALL && nGroup != 0) {
m_pGDB->Rotate( nEnt, ORIG, X_AX, ANG_RIGHT) ;
if ( nGroup == 4)
m_pGDB->Rotate( nEnt, ORIG, Z_AX, -ANG_RIGHT) ;
else
m_pGDB->Rotate( nEnt, ORIG, Z_AX, ANG_RIGHT) ;
}
// 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<ICurveComposite> 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<ISurfTriMesh> 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<ICurveComposite> 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<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> pStmNew1 ;
PtrOwner<ISurfTriMesh> 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<ISurfTriMesh> 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<ISurfTriMesh> 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<ICurveComposite> pCrvCompo( GetFreeContourCurve( nProcId, frRef, nContType == FCT_NAIL)) ;
if ( IsNull( pCrvCompo))
break ;
if ( ! pCrvCompo->IsValid())
continue ;
BBox3d b3Crv ; double dCrvDim = 0 ;
if ( ! pCrvCompo->GetLocalBBox( b3Crv) || ! b3Crv.GetDiameter( dCrvDim) || dCrvDim > FC_MAX_DIM) {
string sOut = " Error : Free Contour too big (" + ToString( dCrvDim) + ")" ;
LOG_ERROR( GetEExLogger(), sOut.c_str())
bOk = false ;
continue ;
}
// eventuale secondo contorno
PtrOwner<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> 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_FINE_APPROX, CRV_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL) ||
! pCrvCompo2->ApproxWithLines( CRV_LIN_FINE_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
bool bTrans = false ;
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)) {
bTrans = true ;
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) ;
}
}
// verifico se ci sono torsioni, nel qual caso spezzo opportunamente
bool bTwist = false ;
if ( ! bTrans && PL.GetPointNbr() == PL2.GetPointNbr()) {
// recupero le liste di punti delle due polilinee
PNTULIST& lstPU1 = PL.GetUPointList() ;
PNTULIST& lstPU2 = PL2.GetUPointList() ;
// ciclo su entrambe le liste
auto PU1p = lstPU1.begin() ;
auto PU1s = next( PU1p) ;
auto PU2p = lstPU2.begin() ;
auto PU2s = next( PU2p) ;
while ( PU1s != lstPU1.end() && PU2s != lstPU2.end()) {
// se il quadrilatero torto oltre il limite, lo divido in due
double dDist ;
DistLineLine dstDiag( PU1p->first, PU2s->first, PU2p->first, PU1s->first) ;
if ( dstDiag.GetDist( dDist) && dDist > FC_TWIST_DIAG_DIST) {
bTwist = true ;
// inserisco punti medi
lstPU1.emplace( PU1s, Media( PU1p->first, PU1s->first), ( PU1p->second + PU1s->second) / 2) ;
lstPU2.emplace( PU2s, Media( PU2p->first, PU2s->first), ( PU2p->second + PU2s->second) / 2) ;
// aggiorno iteratori
PU1s = next( PU1p) ;
PU2s = next( PU2p) ;
}
// altrimenti passo al successivo quadrilatero
else {
PU1p = PU1s ;
PU1s = next( PU1p) ;
PU2p = PU2s ;
PU2s = next( PU2p) ;
}
}
}
// Creo la superficie rigata corrispondente
// Se con torsione e senza svuotatura, tramite bezier
if ( bTwist && ! ( bClosed && bPocket)) {
PtrOwner<ISurfBezier> pSbz( GetSurfBezierRuled( pCrvCompo, pCrvCompo2, ISurfBezier::RLT_B_ISOPAR)) ;
if ( ! IsNull( pSbz))
pStm.Set( pSbz->GetApproxSurf( 10 * EPS_SMALL)) ;
}
// altrimenti direttamente
else {
pStm.Set( CreateSurfTriMesh()) ;
if ( ! IsNull( pStm)) {
if ( ! pStm->CreateByTwoCurves( PL, PL2, ISurfTriMesh::RLT_ISOPAR_SMOOTH))
pStm.Reset() ;
}
}
if ( ! IsNull( pStm)) {
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<ISurfTriMesh> 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<ICurveComposite> 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<ICurveComposite> 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<ISurfTriMesh> 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<ISurfTriMesh> 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_SMOOTH) ;
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<ISurfTriMesh> 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::GetDistanceBeamPlane( const Plane3d& plPlane)
{
// 0 -> si intersecano, > 0 -> trave tutta dal lato positivo del piano, < 0 -> trave tutta dal lato negativo
double dMinElev = INFINITO ;
double dMaxElev = -INFINITO ;
int nPos = 0, nOn = 0 , nNeg = 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 dDist = DistPointPlane( ptP, plPlane) ;
if ( dDist > -EPS_SMALL && dDist < EPS_SMALL)
nOn ++ ;
else if ( dDist > 0)
nPos ++ ;
else
nNeg ++ ;
dMinElev = min( dDist, dMinElev) ;
dMaxElev = max( dDist, dMaxElev) ;
}
if ( ( nPos > 0 && nNeg > 0) || nOn > 0)
return 0 ;
else if ( nPos > 0)
return dMinElev ;
else
return dMaxElev ;
}
//----------------------------------------------------------------------------
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<ISurfTriMesh> 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<ICurveComposite> pCrv( CreateCurveComposite()) ;
if ( IsNull( pCrv) || ! pCrv->FromPolyLine( Polyg.GetPolyLine()))
return false ;
PtrOwner<ISurfFlatRegion> 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<ICurveComposite> pCrv( CreateCurveComposite()) ;
if ( IsNull( pCrv) || ! pCrv->FromPolyLine( Polyg.GetPolyLine()))
return nullptr ;
PtrOwner<ISurfFlatRegion> 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<ISurfFlatRegion> 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<ICurve> 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<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return nullptr ;
// recupero le entit free contour
int nEnt = -1 ;
for ( int i = nStartInd + 1 ; i < ssize( dqFce) ; ++ 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<ICurveLine> 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<ICurve> 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<ICurveComposite> 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<ICurveComposite> 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<ICurveComposite> 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<ISurfTriMesh> pStm( GetSurfTriMeshEmpty()) ;
if ( IsNull( pStm))
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) ;
}