91d1260d8a
- in import BTL aggiunta gestione Tenone Coda di Rondine non limitato dal lato dell'arrotondamento (P04=1).
9189 lines
395 KiB
C++
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) ;
|
|
} |