Files
EgtExecutor/EXE_GeoInters.cpp
Dario Sassi 7412a3085f EgtExecutor :
- la funzione Exe/Lua SurfBezierParamsFromPoint ora restituisce solo i valori dei parametri U e V che corrispondono al punto
- piccole migliorie.
2026-03-13 13:33:46 +01:00

1508 lines
60 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2018-2018
//----------------------------------------------------------------------------
// File : EXE_GeoInters.cpp Data : 27.09.18 Versione : 1.9i4
// Contenuto : Funzioni di intersezioni tra oggetto geometrici per EXE.
//
//
//
// Modifiche : 27.09.18 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "EXE.h"
#include "EXE_Const.h"
#include "EXE_Macro.h"
#include "AuxTools.h"
#include "GeoTools.h"
#include "/EgtDev/Include/EXeExecutor.h"
#include "/EgtDev/Include/EXeConst.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EGkCurveLocal.h"
#include "/EgtDev/Include/EGkStmStandard.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkSurfLocal.h"
#include "/EgtDev/Include/EGkVolZmap.h"
#include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
#include "/EgtDev/Include/EGkIntersPlaneBox.h"
#include "/EgtDev/Include/EGkIntersLineSurfBez.h"
#include "/EgtDev/Include/EGkIntersPlaneSurfTm.h"
#include "/EgtDev/Include/EGkIntersPlaneVolZmap.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkIntersCurveSurfTm.h"
#include "/EgtDev/Include/EGkIntersSurfTmSurfTm.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//-------------------------------------------------------------------------------
static bool
MyLineCurveInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
vInters.clear() ;
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero il riferimento di calcolo
Frame3d frCalc ;
if ( nRefType == RTY_GLOB)
frCalc = GLOB_FRM ;
else if ( nRefType == RTY_GRID)
frCalc = pGeomDB->GetGridFrame() ;
else {
if ( ! pGeomDB->GetGlobFrame( nId, frCalc))
return false ;
}
// recupero la curva in locale al gruppo destinazione
CurveLocal CrvLoc( pGeomDB, nId, frCalc) ;
// calcolo l'ingombro della curva
BBox3d b3Crv ;
if ( ! CrvLoc->GetLocalBBox( b3Crv))
return false ;
b3Crv.Expand( 100 * EPS_SMALL) ;
// definisco la linea (punto e direzione sono già nel riferimento di calcolo)
double dLen = 2 * floor( b3Crv.MaxDistFromPoint( ptP)) ;
double dOffs = -dLen / 2 ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( IsNull( pLine) || ! pLine->SetPVL( ptP + dOffs * vtDir, vtDir, dLen) )
return false ;
// intersezione fra le curve nel piano di calcolo
IntersCurveCurve intCC( *pLine, *CrvLoc, true) ;
int nInters = intCC.GetIntersCount() ;
// recupero i risultati
for ( int i = 0 ; i < nInters ; i++) {
IntCrvCrvInfo aInfo ;
intCC.GetIntCrvCrvInfo( i, aInfo) ;
// se intersezione puntuale
if ( ! aInfo.bOverlap) {
double dDist = dOffs + aInfo.IciA[0].dU * dLen ;
int nType = CLT_NONE ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN) {
if ( aInfo.IciA[0].nNextTy == ICCT_IN)
nType = CLT_TOUCH_IN ;
else if ( aInfo.IciA[0].nNextTy == ICCT_OUT)
nType = CLT_OUT ;
}
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT) {
if ( aInfo.IciA[0].nNextTy == ICCT_IN)
nType = CLT_IN ;
else if ( aInfo.IciA[0].nNextTy == ICCT_OUT)
nType = CLT_TOUCH_OUT ;
}
vInters.emplace_back( nType, dDist) ;
}
// altrimenti sovrapposizione
else {
// inizio
double dDist1 = dOffs + aInfo.IciA[0].dU * dLen ;
int nType1 = CLT_NONE ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nType1 = CLT_TGINI_IN ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
nType1 = CLT_TGINI_OUT ;
vInters.emplace_back( nType1, dDist1) ;
// fine
double dDist2 = dOffs + aInfo.IciA[1].dU * dLen ;
int nType2 = CLT_NONE ;
if ( aInfo.IciA[1].nNextTy == ICCT_IN)
nType2 = CLT_TGFIN_IN ;
else if ( aInfo.IciA[1].nNextTy == ICCT_OUT)
nType2 = CLT_TGFIN_OUT ;
vInters.emplace_back( nType2, dDist2) ;
}
}
return true ;
}
//-------------------------------------------------------------------------------
bool
ExeLineCurveInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
// eseguo
bool bOk = MyLineCurveInters( ptP, vtDir, nId, nRefType, vInters) ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtLineCurveInters({" + ToString( ptP) + "},{" +
ToString( vtDir) + "},{" +
ToString( nId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Ok=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco stato esecuzione
return bOk ;
}
//-------------------------------------------------------------------------------
bool
ExeLineBoxInters( const Point3d& ptP, const Vector3d& vtDir, const BBox3d& b3Box,
INTDBLVECTOR& vInters)
{
// eseguo
bool bOk = IntersLineBox( ptP, vtDir, 1, b3Box, vInters, false) ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtLineBoxInters({" + ToString( ptP) + "},{" +
ToString( vtDir) + "},{" +
ToString( b3Box) + "})" +
" -- Ok=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return bOk ;
}
//-------------------------------------------------------------------------------
static bool
MyLineSurfTmInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
vInters.clear() ;
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero la superficie TriMesh
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nId)) ;
if ( pStm == nullptr)
return false ;
// recupero il suo riferimento globale
Frame3d frSurf ;
if ( ! pGeomDB->GetGlobFrame( nId, frSurf))
return false ;
// porto in locale il punto e la direzione della linea
Point3d ptPL = GetPointLocal( pGeomDB, ptP, nRefType, frSurf) ;
Vector3d vtDirL = GetVectorLocal( pGeomDB, vtDir, nRefType, frSurf) ;
vtDirL.Normalize() ;
// calcolo l'ingombro della trimesh
BBox3d b3Surf ;
if ( ! pStm->GetLocalBBox( b3Surf))
return false ;
// calcolo l'intersezione
double dLen = b3Surf.MaxDistFromPoint( ptPL) ;
ILSIVECTOR vInfo ;
if ( ! IntersLineSurfTm( ptPL, vtDirL, dLen, *pStm, vInfo, false))
return false ;
// filtro le intersezioni
FilterLineSurfTmInters( vInfo, vInters) ;
return true ;
}
//-------------------------------------------------------------------------------
bool
ExeLineSurfTmInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
// eseguo
bool bOk = MyLineSurfTmInters( ptP, vtDir, nId, nRefType, vInters) ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtLineSurfTmInters({" + ToString( ptP) + "},{" +
ToString( vtDir) + "}," +
ToString( nId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Ok=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return bOk ;
}
//-------------------------------------------------------------------------------
static bool
MyLineSurfBzInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType, INTDBLVECTOR& vInters)
{
vInters.clear() ;
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero la superficie Bezier
const ISurfBezier* pSbz = GetSurfBezier( pGeomDB->GetGeoObj( nId)) ;
if ( pSbz == nullptr)
return false ;
// recupero il suo riferimento globale
Frame3d frSurf ;
if ( ! pGeomDB->GetGlobFrame( nId, frSurf))
return false ;
// porto in locale il punto e la direzione della linea
Point3d ptPL = GetPointLocal( pGeomDB, ptP, nRefType, frSurf) ;
Vector3d vtDirL = GetVectorLocal( pGeomDB, vtDir, nRefType, frSurf) ;
vtDirL.Normalize() ;
// calcolo l'ingombro della Bezier
BBox3d b3Surf ;
if ( ! pSbz->GetLocalBBox( b3Surf))
return false ;
// calcolo l'intersezione
double dLen = b3Surf.MaxDistFromPoint( ptPL) ;
ILSBIVECTOR vInfo ;
if ( ! IntersLineSurfBz( ptPL, vtDirL, dLen, pSbz, vInfo, false))
return false ;
// filtro le intersezioni
FilterLineSurfBzInters( vInfo, vInters) ;
return true ;
}
//-------------------------------------------------------------------------------
bool
ExeLineSurfBzInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
// eseguo
bool bOk = MyLineSurfBzInters( ptP, vtDir, nId, nRefType, vInters) ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtLineSurfBzInters({" + ToString( ptP) + "},{" +
ToString( vtDir) + "}," +
ToString( nId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Ok=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return bOk ;
}
//-------------------------------------------------------------------------------
static bool
MyLineVolZmapInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
vInters.clear() ;
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero lo Zmap
IVolZmap* pVZM = GetVolZmap( pGeomDB->GetGeoObj( nId)) ;
if ( pVZM == nullptr)
return false ;
// recupero il suo riferimento globale
Frame3d frZmap ;
if ( ! pGeomDB->GetGlobFrame( nId, frZmap))
return false ;
// porto in locale il punto e la direzione della linea
Point3d ptPL = GetPointLocal( pGeomDB, ptP, nRefType, frZmap) ;
Vector3d vtDirL = GetVectorLocal( pGeomDB, vtDir, nRefType, frZmap) ;
vtDirL.Normalize() ;
// calcolo l'intersezione
ILZIVECTOR vInfo ;
if ( ! IntersLineVolZmap( ptPL, vtDirL, *pVZM, vInfo))
return false ;
// filtro le intersezioni
FilterLineVolZmapInters( vInfo, vInters) ;
return true ;
}
//-------------------------------------------------------------------------------
bool
ExeLineVolZmapInters( const Point3d& ptP, const Vector3d& vtDir, int nId, int nRefType,
INTDBLVECTOR& vInters)
{
// eseguo
bool bOk = MyLineVolZmapInters( ptP, vtDir, nId, nRefType, vInters) ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtLineVolZmapInters({" + ToString( ptP) + "},{" +
ToString( vtDir) + "}," +
ToString( nId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Ok=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco stato operazione
return bOk ;
}
//-------------------------------------------------------------------------------
static int
MyAddPlaneIntersResultToGeomDB( IGeomDB* pGeomDB, const PNTVECTOR& vPnt, const BIPNTVECTOR& vBpt, const TRIA3DVECTOR& vTria,
const Frame3d& frOrig, const Frame3d& frDest, int nId, int nDestGrpId, const Vector3d& vtExtr,
double dToler, int& nPntCount, int& nCrvCount, int& nSrfCount)
{
// Inserisco il risultato nel DB
int nFirstId = GDB_ID_NULL ;
// Inserisco i punti nel DB
for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) {
// creo il punto
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
if ( IsNull( pGeoPnt))
return GDB_ID_NULL ;
// setto il punto
pGeoPnt->Set( vPnt[i]) ;
// porto il punto nel riferimento destinazione
pGeoPnt->LocToLoc( frOrig, frDest) ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pGeoPnt)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio il materiale
if ( ! pGeomDB->CopyMaterial( nId, nNewId))
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nPntCount ;
}
// Inserisco le curve nel DB (dopo averle concatenate)
ChainCurves chainC ;
chainC.Init( false, dToler, int( vBpt.size())) ;
DBLVECTOR vdLen ; vdLen.reserve( vBpt.size()) ;
for ( int i = 0 ; i < int( vBpt.size()) ; ++ i) {
Vector3d vtDir = vBpt[i].second - vBpt[i].first ;
vdLen.emplace_back( vtDir.Len()) ;
vtDir.Normalize() ;
if ( ! chainC.AddCurve( i + 1, vBpt[i].first, vtDir, vBpt[i].second, vtDir))
return GDB_ID_NULL ;
}
// recupero i percorsi concatenati
// il punto di inizio viene scelto come lo start di un tratto più lungo della tolleranza in modo da evitare casi problematici
// del chain in cui percorsi formati da tratti di lunghezza inferiore alla tolleranza vengono individuati erroneamente come chiusi
// interrompendo il loro concatenamento con le altre curve
Point3d ptNear = ( vBpt.empty() ? ORIG : vBpt[0].first) ;
for ( int i = 0 ; i < int( vdLen.size()) ; ++ i) {
if ( vdLen[i] > 2 * dToler) {
ptNear = vBpt[i].first ;
break ;
}
}
INTVECTOR vId ;
while ( chainC.GetChainFromNear( ptNear, false, vId)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return GDB_ID_NULL ;
// recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita
bool bAdded = true ;
for ( int i = 0 ; i < int( vId.size()) ; ++ i) {
// creo un segmento di retta
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( IsNull( pLine))
return GDB_ID_NULL ;
// recupero gli estremi (non vanno mai invertiti per opzione di concatenamento)
int nInd = abs( vId[i]) - 1 ;
Point3d ptStart = ( bAdded ? vBpt[nInd].first : ptNear) ;
Point3d ptEnd = vBpt[nInd].second ;
// provo ad accodarlo alla composita
bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 &&
pLine->Set( ptStart, ptEnd) &&
pCrvCompo->AddCurve( Release( pLine), true, dToler)) ;
ptNear = ( bAdded ? ptEnd : ptStart) ;
// rendo invalida la sua lunghezza per non ritrovarlo come tratto iniziale del percorso successivo
vdLen[nInd] = -1 ;
}
// se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro
double dCrvLen ;
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler)
continue ;
// se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene
Point3d ptStart, ptEnd ;
if ( pCrvCompo->GetStartPoint( ptStart) &&
pCrvCompo->GetEndPoint( ptEnd) &&
AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) &&
! AreSamePointApprox( ptStart, ptEnd)) {
// porto il punto finale a coincidere esattamente con l'inizio
pCrvCompo->ModifyEnd( ptStart) ;
}
// assegno estrusione come direzione normale al piano
pCrvCompo->SetExtrusion( vtExtr) ;
// unisco segmenti allineati
pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ;
// porto la curva nel riferimento destinazione
pCrvCompo->LocToLoc( frOrig, frDest) ;
// la inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pCrvCompo)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio il materiale
if ( ! pGeomDB->CopyMaterial( nId, nNewId))
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nCrvCount ;
// scelgo il nuovo punto di inizio
for ( int i = 0 ; i < int( vdLen.size()) ; ++ i) {
if ( vdLen[i] > 2 * dToler) {
ptNear = vBpt[i].first ;
break ;
}
}
}
// Inserisco i triangoli nel DB (dopo averli uniti in una superficie trimesh)
StmFromTriangleSoup StmFts ;
if ( ! StmFts.Start())
return GDB_ID_NULL ;
for ( int i = 0 ; i < int( vTria.size()) ; ++ i)
// inserisco il triangolo nella nuova superficie
StmFts.AddTriangle( vTria[i]) ;
// valido la superficie e calcolo le adiacenze
if ( ! StmFts.End())
return GDB_ID_NULL ;
// se superficie con triangoli
PtrOwner<ISurfTriMesh> pNewStm( StmFts.GetSurf()) ;
if ( ! IsNull( pNewStm) && pNewStm->GetTriangleCount() > 0) {
// porto la superficie nel riferimento destinazione
pNewStm->LocToLoc( frOrig, frDest) ;
// la inserisco nel DB
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pNewStm)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio il materiale
if ( ! pGeomDB->CopyMaterial( nId, nNewId))
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nSrfCount ;
}
return nFirstId ;
}
//-------------------------------------------------------------------------------
static int
MyPlaneCurveInters( const Point3d& ptOn, const Vector3d& vtN, int nId, int nDestGrpId, int nRefType, int& nCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// recupero la curva
const ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nId)) ;
if ( pCrv == nullptr)
return GDB_ID_NULL ;
// recupero il suo riferimento globale
Frame3d frCrv ;
if ( ! pGeomDB->GetGlobFrame( nId, frCrv))
return GDB_ID_NULL ;
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// definisco il piano in locale
Point3d ptOnL = GetPointLocal( pGeomDB, ptOn, nRefType, frCrv) ;
Vector3d vtNL = GetVectorLocal( pGeomDB, vtN, nRefType, frCrv) ;
Plane3d plPlane ;
plPlane.Set( ptOnL, vtNL) ;
// approssimo la curva con polyline
PolyLine PL ;
if ( ! pCrv->ApproxWithLines( 10 * EPS_SMALL, 15, ICurve::APL_SPECIAL, PL))
return GDB_ID_NULL ;
// per ogni tratto della polyline cerco l'intersezione con il piano
PNTVECTOR vPnt ;
BIPNTVECTOR vBpt ;
Point3d ptS, ptE ;
PL.GetFirstPoint( ptS) ;
while ( PL.GetNextPoint( ptE)) {
Point3d ptInt ;
int nRes = IntersLinePlane( ptS, ptE, plPlane, ptInt) ;
if ( nRes == ILPT_INPLANE)
vBpt.emplace_back( ptS, ptE) ;
else if ( nRes != ILPT_NO)
vPnt.emplace_back( ptInt) ;
// aggiorno ptS per tratto successivo
ptS = ptE ;
}
// elimino segmenti ripetuti
for ( int i = 0 ; i < ( int)vBpt.size() ; ) {
bool bFound = false ;
for ( int j = i + 1 ; j < ( int)vBpt.size() ; j ++) {
if (( AreSamePointApprox( vBpt[i].first, vBpt[j].first) && AreSamePointApprox( vBpt[i].second, vBpt[j].second)) ||
( AreSamePointApprox( vBpt[i].first, vBpt[j].second) && AreSamePointApprox( vBpt[i].second, vBpt[j].first))) {
bFound = true ;
break ;
}
}
if ( bFound)
vBpt.erase( vBpt.begin() + i) ;
else
i ++ ;
}
// elimino punti ripetuti
for ( int i = 0 ; i < ( int)vPnt.size() ; ) {
bool bFound = false ;
// cerco tra i punti rimanenti
for ( int j = i + 1 ; j < ( int)vPnt.size() ; j ++) {
if ( AreSamePointApprox( vPnt[i], vPnt[j])) {
bFound = true ;
break ;
}
}
// cerco eventualmente tra i segmenti
if ( ! bFound) {
for ( int j = 0 ; j < ( int)vBpt.size() ; j ++) {
if ( AreSamePointApprox( vPnt[i], vBpt[j].first) || AreSamePointApprox( vPnt[i], vBpt[j].second)) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vPnt.erase( vPnt.begin() + i) ;
else
i ++ ;
}
// aggiungo i risultati al DB geometrico
int nPntCount{ 0}, nCrvCount{ 0}, nTmp{ 0} ;
int nFirstId = MyAddPlaneIntersResultToGeomDB( pGeomDB, vPnt, vBpt, TRIA3DVECTOR(), frCrv, frDest, nId, nDestGrpId, vtNL,
EPS_SMALL, nPntCount, nCrvCount, nTmp) ;
nCount = nPntCount + nCrvCount ;
// restituisco l'identificativo della prima entità creata
return nFirstId ;
}
//-------------------------------------------------------------------------------
int
ExePlaneCurveInters( const Point3d& ptOn, const Vector3d& vtN, int nId, int nDestGrpId, int nRefType, int* pnCount)
{
// eseguo
int nCount{ 0} ;
int nFirstId = MyPlaneCurveInters( ptOn, vtN, nId, nDestGrpId, nRefType, nCount) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnCount != nullptr)
*pnCount = nCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtPlaneCurveInters({" + ToString( ptOn) + "},{" +
ToString( vtN) + "},{" +
ToString( nId) + "," +
ToString( nDestGrpId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Id=" + ToString( nFirstId) + ", nCnt=" + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
static int
MyPlaneBoxInters( const Point3d& ptOn, const Vector3d& vtN, const BBox3d& b3Box, int nDestGrpId, int nRefType,
int& nPntCount, int& nCrvCount, int& nSrfCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// recupero il riferimento sorgente
Frame3d frSou ;
if ( nRefType == RTY_GLOB)
frSou = Frame3d() ;
else if ( nRefType == RTY_GRID)
frSou = pGeomDB->GetGridFrame() ;
else // ( nRefType == RTY_LOC)
frSou = frDest ;
// calcolo il piano
Plane3d plPlane ;
if ( ! plPlane.Set( ptOn, vtN))
return GDB_ID_NULL ;
// eseguo l'intersezione
PNTVECTOR vPnt ;
BIPNTVECTOR vBpt ;
TRIA3DVECTOR vTria ;
if ( ! IntersPlaneBox( plPlane, b3Box, vPnt, vBpt, vTria))
return GDB_ID_NULL ;
// porto le intersezioni nel riferimento destinazione
for ( auto& Pnt : vPnt)
Pnt.LocToLoc( frSou, frDest) ;
for ( auto& Bpt : vBpt) {
Bpt.first.LocToLoc( frSou, frDest) ;
Bpt.second.LocToLoc( frSou, frDest) ;
}
for ( auto& Tria : vTria)
Tria.LocToLoc( frSou, frDest) ;
// porto la normale al piano nel riferimento destinazione
Vector3d vtNL = vtN ;
vtNL.LocToLoc( frSou, frDest) ;
// Inserisco il risultato nel DB
int nFirstId = GDB_ID_NULL ;
// Inserisco i punti nel DB
for ( size_t i = 0 ; i < vPnt.size() ; ++ i) {
// creo il punto
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
if ( IsNull( pGeoPnt))
return GDB_ID_NULL ;
// setto il punto
pGeoPnt->Set( vPnt[i]) ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pGeoPnt)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nPntCount ;
}
// Concateno i tratti di curva
double dToler = 2 * EPS_SMALL ;
ChainCurves chainC ;
chainC.Init( false, dToler, int( vBpt.size())) ;
for ( size_t i = 0 ; i < vBpt.size() ; ++ i) {
Vector3d vtDir = vBpt[i].second - vBpt[i].first ;
vtDir.Normalize() ;
if ( ! chainC.AddCurve( int( i) + 1, vBpt[i].first, vtDir, vBpt[i].second, vtDir))
return GDB_ID_NULL ;
}
// recupero i percorsi concatenati
Point3d ptNear = ( vBpt.empty() ? ORIG : vBpt[0].first) ;
INTVECTOR vId ;
while ( chainC.GetChainFromNear( ptNear, false, vId)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return GDB_ID_NULL ;
// recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita
for ( size_t i = 0 ; i < vId.size() ; ++ i) {
// creo una segmento di retta
int nInd = abs( vId[i]) - 1 ;
bool bInvert = ( vId[i] < 0) ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( IsNull( pLine) || ! pLine->Set( vBpt[nInd].first, vBpt[nInd].second))
return GDB_ID_NULL ;
if ( bInvert)
pLine->Invert() ;
// lo accodo alla composita
if ( ! pCrvCompo->AddCurve( Release( pLine), true, dToler))
return GDB_ID_NULL ;
// aggiorno il prossimo near
ptNear = vBpt[nInd].second ;
}
// se lunghezza curva inferiore a 5 volte la tolleranza, la salto
double dCrvLen ;
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler)
continue ;
// se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene
Point3d ptStart, ptEnd ;
if ( pCrvCompo->GetStartPoint( ptStart) &&
pCrvCompo->GetEndPoint( ptEnd) &&
AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) &&
! AreSamePointApprox( ptStart, ptEnd)) {
// porto il punto finale a coincidere esattamente con l'inizio
pCrvCompo->ModifyEnd( ptStart) ;
}
// assegno estrusione come direzione normale al piano
pCrvCompo->SetExtrusion( vtNL) ;
// unisco segmenti allineati
pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ;
// la inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pCrvCompo)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nCrvCount ;
}
// Se ci sono segmenti ma non sono state create curve, aggiungo punto nel loro centro
if ( ! vBpt.empty() && nCrvCount == 0) {
BBox3d b3Crv ;
for ( size_t i = 0 ; i < vBpt.size() ; ++ i) {
b3Crv.Add( vBpt[i].first) ;
b3Crv.Add( vBpt[i].second) ;
}
if ( ! b3Crv.IsEmpty()) {
// creo il punto
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
if ( IsNull( pGeoPnt))
return GDB_ID_NULL ;
// setto il punto
Point3d ptCen ; b3Crv.GetCenter( ptCen) ;
pGeoPnt->Set( ptCen) ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pGeoPnt)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nPntCount ;
}
}
// Costruisco una superficie trimesh dall'insieme di triangoli
StmFromTriangleSoup StmFts ;
if ( ! StmFts.Start())
return GDB_ID_NULL ;
for ( size_t i = 0 ; i < vTria.size() ; ++ i)
// inserisco il triangolo nella nuova superficie
StmFts.AddTriangle( vTria[i]) ;
// valido la superficie e calcolo le adiacenze
if ( ! StmFts.End())
return GDB_ID_NULL ;
// se superficie con triangoli
PtrOwner<ISurfTriMesh> pNewStm( StmFts.GetSurf()) ;
if ( ! IsNull( pNewStm) && pNewStm->GetTriangleCount() > 0) {
// la inserisco nel DB
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pNewStm)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nSrfCount ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
int
ExePlaneBoxInters( const Point3d& ptOn, const Vector3d& vtN, const BBox3d& b3Box, int nDestGrpId, int nRefType,
int* pnPntCount, int* pnCrvCount, int* pnSrfCount)
{
// eseguo
int nPntCount{ 0}, nCrvCount{ 0}, nSrfCount{ 0} ;
int nFirstId = MyPlaneBoxInters( ptOn, vtN, b3Box, nDestGrpId, nRefType, nPntCount, nCrvCount, nSrfCount) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnPntCount != nullptr)
*pnPntCount = nPntCount ;
if ( pnCrvCount != nullptr)
*pnCrvCount = nCrvCount ;
if ( pnSrfCount != nullptr)
*pnSrfCount = nSrfCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtPlaneBoxInters({" + ToString( ptOn) + "},{" +
ToString( vtN) + "},{" +
ToString( b3Box) + "}," +
ToString( nDestGrpId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Id1=" + ToString( nFirstId) + ", PntNbr=" + ToString( nPntCount) +
", CrvNbr=" + ToString( nCrvCount) + ", SrfNbr=" + ToString( nSrfCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
static int
MyPlaneSurfTmInters( const Point3d& ptOn, const Vector3d& vtN, int nId, int nDestGrpId, int nRefType, double dToler,
int& nPntCount, int& nCrvCount, int& nSrfCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// recupero la superficie TriMesh
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nId)) ;
if ( pStm == nullptr)
return GDB_ID_NULL ;
// recupero il suo riferimento globale
Frame3d frSurf ;
if ( ! pGeomDB->GetGlobFrame( nId, frSurf))
return GDB_ID_NULL ;
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// porto in locale il punto e la normale del piano
Point3d ptOnL = GetPointLocal( pGeomDB, ptOn, nRefType, frSurf) ;
Vector3d vtNL = GetVectorLocal( pGeomDB, vtN, nRefType, frSurf) ;
// calcolo il piano di intersezione
Plane3d plPlane ;
if ( ! plPlane.Set( ptOnL, vtNL))
return GDB_ID_NULL ;
// eseguo l'intersezione
PNTVECTOR vPnt ;
BIPNTVECTOR vBpt ;
TRIA3DVECTOR vTria ;
if ( ! IntersPlaneSurfTm( plPlane, *pStm, vPnt, vBpt, vTria))
return GDB_ID_NULL ;
// inserisco il risultato dell'intersezione nel DB
int nFirstId = MyAddPlaneIntersResultToGeomDB( pGeomDB, vPnt, vBpt, vTria, frSurf, frDest, nId, nDestGrpId, plPlane.GetVersN(), dToler,
nPntCount, nCrvCount, nSrfCount) ;
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
int
ExePlaneSurfTmInters( const Point3d& ptOn, const Vector3d& vtN, int nId, int nDestGrpId, int nRefType, double dToler,
int* pnPntCount, int* pnCrvCount, int* pnSrfCount)
{
// eseguo
int nPntCount{ 0}, nCrvCount{ 0}, nSrfCount{ 0} ;
int nFirstId = MyPlaneSurfTmInters( ptOn, vtN, nId, nDestGrpId, nRefType, dToler, nPntCount, nCrvCount, nSrfCount) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnPntCount != nullptr)
*pnPntCount = nPntCount ;
if ( pnCrvCount != nullptr)
*pnCrvCount = nCrvCount ;
if ( pnSrfCount != nullptr)
*pnSrfCount = nSrfCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtPlaneSurfTmInters({" + ToString( ptOn) + "},{" +
ToString( vtN) + "}," +
ToString( nId) + "," +
ToString( nDestGrpId) + "," +
RefTypeToString( nRefType) + "," +
ToString( dToler) + ")" +
" -- Id1=" + ToString( nFirstId) + ", PntNbr=" + ToString( nPntCount) +
", CrvNbr=" + ToString( nCrvCount) + ", SrfNbr=" + ToString( nSrfCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
static int
MyParPlanesSurfTmInters( const Point3d& ptOn, const Vector3d& vtN, const DBLVECTOR& vdDist, int nId, int nDestGrpId, int nRefType, double dToler, int& nGrpCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// recupero la superficie TriMesh
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nId)) ;
if ( pStm == nullptr)
return GDB_ID_NULL ;
// recupero il suo riferimento globale
Frame3d frSurf ;
if ( ! pGeomDB->GetGlobFrame( nId, frSurf))
return GDB_ID_NULL ;
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// porto in locale la normale del piano
Point3d ptOnL = GetPointLocal( pGeomDB, ptOn, nRefType, frSurf) ;
Vector3d vtNL = GetVectorLocal( pGeomDB, vtN, nRefType, frSurf) ;
// costruisco il frame dei piani
Frame3d frPlanes ;
frPlanes.Set( ptOnL, vtNL) ;
// intersezione fra superficie e piani paralleli
IntersParPlanesSurfTm intPlStm( frPlanes, *pStm) ;
int nFirstGrpId = GDB_ID_NULL ;
for ( size_t i = 0 ; i < vdDist.size() ; i++) {
// creo il layer in cui salvare
int nGrpId = pGeomDB->AddGroup( GDB_ID_NULL, nDestGrpId, GLOB_FRM) ;
nGrpCount ++ ;
if ( nFirstGrpId == GDB_ID_NULL)
nFirstGrpId = nGrpId ;
// cerco l'intersezione con il piano
PNTVECTOR vPnt ;
BIPNTVECTOR vBpt ;
TRIA3DVECTOR vTria ;
if ( ! intPlStm.GetInters( vdDist[i], vPnt, vBpt, vTria)) {
string sErr = "Error on ParPlanesStmInters at distance " + ToString( vdDist[i]) ;
LOG_ERROR( GetLogger(), sErr.c_str()) ;
continue ;
}
// inserisco il risultato nel DB
int nTmp{ 0} ;
MyAddPlaneIntersResultToGeomDB( pGeomDB, vPnt, vBpt, vTria, frSurf, frDest, nId, nGrpId, vtNL, dToler, nTmp, nTmp, nTmp) ;
}
// restituisco l'identificativo del primo gruppo creato
return nFirstGrpId ;
}
//-------------------------------------------------------------------------------
int
ExeParPlanesSurfTmInters( const Point3d& ptOn, const Vector3d& vtN, const DBLVECTOR& vdDist, int nId, int nDestGrpId, int nRefType, double dToler,
int* pnGrpCount)
{
// eseguo
int nGrpCount{ 0} ;
int nFirstId = MyParPlanesSurfTmInters( ptOn, vtN, vdDist, nId, nDestGrpId, nRefType, dToler, nGrpCount) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnGrpCount != nullptr)
*pnGrpCount = nGrpCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtParPlanesSurfTmInters({" + ToString( ptOn) + "},{" +
ToString( vtN) + "},{" +
ToString( vdDist) + "}," +
ToString( nId) + "," +
ToString( nDestGrpId) + "," +
RefTypeToString( nRefType) + "," +
ToString( dToler) + ")" +
" -- Id=" + ToString( nFirstId) + ", GrpCnt=" + ToString( nGrpCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//----------------------------------------------------------------------------
int
MyPlaneVolZmapInters( const Point3d& ptOn, const Vector3d& vtN, int nId, int nDestGrpId, int nRefType, int& nCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero il riferimento locale
Frame3d frLoc ;
if ( ! pGeomDB->GetGlobFrame( nId, frLoc))
return GDB_ID_NULL ;
// recupero il riferimento destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// porto in locale il punto e la normale del piano
Point3d ptOnL = GetPointLocal( pGeomDB, ptOn, nRefType, frLoc) ;
Vector3d vtNL = GetVectorLocal( pGeomDB, vtN, nRefType, frLoc) ;
// calcolo il piano di intersezione
Plane3d plPlane ;
if ( ! plPlane.Set( ptOnL, vtNL))
return GDB_ID_NULL ;
// recupero lo Zmap e calcolo l'intersezione
IVolZmap* pVZM = GetVolZmap( pGeomDB->GetGeoObj( nId)) ;
ICURVEPOVECTOR vpLoop ;
if ( pVZM == nullptr || ! IntersPlaneVolZmap( plPlane, *pVZM, vpLoop))
return GDB_ID_NULL ;
// inserisco le curve nel gruppo destinazione
int nFirstId = GDB_ID_NULL ;
for ( size_t i = 0 ; i < vpLoop.size() ; ++ i) {
PtrOwner<ICurve> pCrv( Release( vpLoop[i])) ;
if ( IsNull( pCrv))
continue ;
pCrv->LocToLoc( frLoc, frDest) ;
// inserisco la curva composita nel gruppo destinazione
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, ::Release( pCrv)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nCount ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//----------------------------------------------------------------------------
int
ExePlaneVolZmapInters( const Point3d& ptOn, const Vector3d& vtN, int nId, int nDestGrpId, int nRefType, int* pnCount)
{
// eseguo
int nCount = 0 ;
int nFirstId = MyPlaneVolZmapInters( ptOn, vtN, nId, nDestGrpId, nRefType, nCount) ;
if ( pnCount != nullptr)
*pnCount = nCount ;
ExeSetModified() ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtPlaneVolZmapInters({" + ToString( ptOn) + "},{" +
ToString( vtN) + "}," +
IdToString( nId) + "," +
ToString( nDestGrpId) + "," +
RefTypeToString( nRefType) + ")" +
" -- Id=" + ToString( nFirstId) + ",Nbr=" + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
static int
MyCurveCurveInters( int nId1, int nId2, int nDestGrpId, int& nPntCount, int& nCrvCount, bool bOnly3D)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
int nFirstId = GDB_ID_NULL ;
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// recupero le curve in locale al gruppo destinazione
CurveLocal Crv1Loc( pGeomDB, nId1, frDest) ;
CurveLocal Crv2Loc( pGeomDB, nId2, frDest) ;
if( Crv1Loc.Get() == nullptr || Crv2Loc.Get() == nullptr)
return GDB_ID_NULL ;
// intersezione fra le curve nel piano XY locale
IntersCurveCurve intCC( *Crv1Loc, *Crv2Loc, true) ;
int nInters = 0 ;
if ( ! bOnly3D)
nInters = intCC.GetIntersCount() ;
else
nInters = intCC.GetInters3DCount() ;
// recupero i punti risultanti
for ( int i = 0 ; i < nInters ; i++) {
IntCrvCrvInfo aInfo ;
if( ! bOnly3D)
intCC.GetIntCrvCrvInfo( i, aInfo) ;
else
intCC.GetInt3DCrvCrvInfo( i, aInfo) ;
// verifico se punto
if ( ! aInfo.bOverlap) {
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
if ( IsNull( pGeoPnt))
return GDB_ID_NULL ;
pGeoPnt->Set( aInfo.IciA[0].ptI) ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pGeoPnt)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno parametri
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nPntCount ;
}
}
// recupero le curve risultanti
for ( int i = 0 ; i < nInters ; i++) {
IntCrvCrvInfo aInfo ;
if( ! bOnly3D)
intCC.GetIntCrvCrvInfo( i, aInfo) ;
else
intCC.GetInt3DCrvCrvInfo( i, aInfo) ;
// verifico se curva
if ( aInfo.bOverlap) {
PtrOwner<ICurve> pCrvRes( Crv1Loc->CopyParamRange( aInfo.IciA[0].dU, aInfo.IciA[1].dU)) ;
if ( IsNull( pCrvRes))
return GDB_ID_NULL ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pCrvRes)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno parametri
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nCrvCount ;
}
}
return nFirstId ;
}
//-------------------------------------------------------------------------------
int
ExeCurveCurveInters( int nId1, int nId2, int nDestGrpId, int* pnPntCount, int* pnCrvCount, bool bOnly3D)
{
// eseguo
int nPntCount{ 0}, nCrvCount{ 0} ;
int nFirstId = MyCurveCurveInters( nId1, nId2, nDestGrpId, nPntCount, nCrvCount, bOnly3D) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnPntCount != nullptr)
*pnPntCount = nPntCount ;
if ( pnCrvCount != nullptr)
*pnCrvCount = nCrvCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtCurveCurveInters(" + ToString( nId1) + "," +
ToString( nId2) + "," +
ToString( nDestGrpId) + ")" +
" -- Id=" + ToString( nFirstId) + ", nPntCnt=" + ToString( nPntCount) + ", nCrvCnt=" + ToString( nCrvCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
static string
GetCurveSurfTmIntersType( int nFlag)
{
switch ( nFlag) {
case CSIT_OUT_IN : return "OUT->IN" ;
case CSIT_IN_OUT : return "IN->OUT" ;
case CSIT_IN_IN : return "IN->IN" ;
case CSIT_OUT_OUT : return "OUT->OUT" ;
case CSIT_IN_ON : return "IN->ON" ;
case CSIT_ON_IN : return "ON->IN" ;
case CSIT_OUT_ON : return "OUT->ON" ;
case CSIT_ON_OUT : return "ON->OUT" ;
}
return "NONE" ;
}
//-------------------------------------------------------------------------------
static int
MyCurveSurfTmInters( int nCrvId, int nId2, int nDestGrpId, int& nPntCount, int& nCrvCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
int nFirstId = GDB_ID_NULL ;
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// recupero la curva e la superficie in locale al gruppo destinazione
CurveLocal CrvLoc( pGeomDB, nCrvId, frDest) ;
const ICurve* pCrv = GetCurve( CrvLoc) ;
if ( pCrv == nullptr)
return GDB_ID_NULL ;
SurfLocal StmLoc( pGeomDB, nId2, frDest) ;
const ISurfTriMesh* pStm = GetSurfTriMesh( StmLoc) ;
if ( pStm == nullptr)
return GDB_ID_NULL ;
// intersezione filtrata tra la curva e la superficie locali
INTDBLVECTOR vInters ;
if ( ! IntersCurveSurfTmExt( *pCrv, *pStm, 10 * EPS_SMALL, vInters))
return GDB_ID_NULL ;
// recupero i punti e le curve risultanti
for ( int i = 0 ; i < int( vInters.size()) ; i++) {
// verifico se punto
if ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT ||
vInters[i].first == CSIT_IN_IN || vInters[i].first == CSIT_OUT_OUT || vInters[i].first == CSIT_NONE) {
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
if ( IsNull( pGeoPnt))
return GDB_ID_NULL ;
Point3d ptP ;
pCrv->GetPointD1D2( vInters[i].second, ICurve::FROM_MINUS, ptP) ;
pGeoPnt->Set( ptP) ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pGeoPnt)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno parametri
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nPntCount ;
// assegno info di tipo
pGeomDB->SetInfo( nNewId, "CSI", GetCurveSurfTmIntersType( vInters[i].first) +
" (" + ToString( vInters[i].second) + ")") ;
}
// altrimenti dovrebbe essere sovrapposizione
else {
// indice di inizio
int h = ( i > 0 ? i - 1 : int( vInters.size()) - 1) ;
// verifico se sovrapposizione
if ( ( vInters[h].first == CSIT_IN_ON || vInters[h].first == CSIT_OUT_ON) &&
( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT)) {
PtrOwner<ICurve> pCrvRes( pCrv->CopyParamRange( vInters[h].second, vInters[i].second)) ;
if ( IsNull( pCrvRes))
return GDB_ID_NULL ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pCrvRes)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// aggiorno parametri
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nCrvCount ;
// assegno info di tipo
pGeomDB->SetInfo( nNewId, "CSI_INI", GetCurveSurfTmIntersType( vInters[h].first) +
" (" + ToString( vInters[h].second) + ")") ;
pGeomDB->SetInfo( nNewId, "CSI_FIN", GetCurveSurfTmIntersType( vInters[i].first) +
" (" + ToString( vInters[i].second) + ")") ;
}
}
}
return nFirstId ;
}
//-------------------------------------------------------------------------------
int
ExeCurveSurfTmInters( int nCrvId, int nStmId, int nDestGrpId, int* pnPntCount, int* pnCrvCount)
{
// eseguo
int nPntCount{ 0}, nCrvCount{ 0} ;
int nFirstId = MyCurveSurfTmInters( nCrvId, nStmId, nDestGrpId, nPntCount, nCrvCount) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnPntCount != nullptr)
*pnPntCount = nPntCount ;
if ( pnCrvCount != nullptr)
*pnCrvCount = nCrvCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtCurveSurfTmInters(" + ToString( nCrvId) + "," +
ToString( nStmId) + "," +
ToString( nDestGrpId) + ")" +
" -- Id=" + ToString( nFirstId) + ", nPntCnt=" + ToString( nPntCount) + ", nCrvCnt=" + ToString( nCrvCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entit
return nFirstId ;
}
//-------------------------------------------------------------------------------
static bool
MyChainCurvesForSurfSurfInters( const BIPNTVECTOR& vBpt, IGeomDB* pGeomDB, int nDestGrpId, int nId1, double dToler,
int& nFirstId, int& nCrvCount)
{
// Concateno i tratti di curva
ChainCurves chainC ;
chainC.Init( false, dToler, int( vBpt.size())) ;
for ( int i = 0 ; i < int( vBpt.size()) ; ++ i) {
Vector3d vtDir = vBpt[i].second - vBpt[i].first ;
vtDir.Normalize() ;
if ( ! chainC.AddCurve( i + 1, vBpt[i].first, vtDir, vBpt[i].second, vtDir))
return false ;
}
// recupero i percorsi concatenati
ICRVCOMPOPOVECTOR vCrvCompo ;
Point3d ptNear = ( vBpt.empty() ? ORIG : vBpt[0].first) ;
INTVECTOR vId ;
while ( chainC.GetChainFromNear( ptNear, true, vId)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return false ;
// recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita
bool bAdded = true ;
for ( int i = 0 ; i < int( vId.size()) ; ++ i) {
// creo un segmento di retta
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( IsNull( pLine))
return GDB_ID_NULL ;
// recupero gli estremi (non vanno mai invertiti per opzione di concatenamento)
int nInd = abs( vId[i]) - 1 ;
Point3d ptStart = ( bAdded ? vBpt[nInd].first : ptNear) ;
Point3d ptEnd = vBpt[nInd].second ;
// provo ad accodarlo alla composita
bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 &&
pLine->Set( ptStart, ptEnd) &&
pCrvCompo->AddCurve( Release( pLine), true, dToler)) ;
ptNear = ( bAdded ? ptEnd : ptStart) ;
}
// se lunghezza curva inferiore a 5 volte la tolleranza, la salto
double dCrvLen ;
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5 * dToler)
continue ;
// unisco segmenti allineati
pCrvCompo->MergeCurves( dToler, ANG_TOL_STD_DEG) ;
// la salvo
vCrvCompo.emplace_back( Release( pCrvCompo)) ;
}
// Ripeto concatenamento sulle curve appena create (per riempire eventuali mini buchi)
chainC.Init( false, dToler, int( vCrvCompo.size())) ;
for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) {
Point3d ptStart ; vCrvCompo[i]->GetStartPoint( ptStart) ;
Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ;
Point3d ptEnd ; vCrvCompo[i]->GetEndPoint( ptEnd) ;
Vector3d vtEnd ; vCrvCompo[i]->GetEndDir( vtEnd) ;
if ( ! chainC.AddCurve( i + 1, ptStart, vtStart, ptEnd, vtEnd))
return false ;
}
// recupero i percorsi concatenati
if ( ! vCrvCompo.empty())
vCrvCompo[0]->GetStartPoint( ptNear) ;
else
ptNear = ORIG ;
while ( chainC.GetChainFromNear( ptNear, true, vId)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return false ;
// inserisco le curve nella composita
for ( int i = 0 ; i < int( vId.size()) ; ++ i) {
// recupero dati
int nInd = abs( vId[i]) - 1 ;
bool bInvert = ( vId[i] < 0) ;
if ( bInvert)
vCrvCompo[nInd]->Invert() ;
// accodo
if ( ! pCrvCompo->AddCurve( Release( vCrvCompo[nInd]), true, 1.1 * dToler))
return false ;
// aggiorno il prossimo near
pCrvCompo->GetEndPoint( ptNear) ;
}
// se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene
Point3d ptStart, ptEnd ;
if ( pCrvCompo->GetStartPoint( ptStart) &&
pCrvCompo->GetEndPoint( ptEnd) &&
AreSamePointEpsilon( ptStart, ptEnd, 5 * dToler) &&
! AreSamePointApprox( ptStart, ptEnd)) {
// porto il punto finale a coincidere esattamente con l'inizio
pCrvCompo->ModifyEnd( ptStart) ;
}
// unisco segmenti allineati
pCrvCompo->MergeCurves( dToler, ANG_TOL_STD_DEG) ;
// la inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pCrvCompo)) ;
if ( nNewId == GDB_ID_NULL)
return false ;
// copio il materiale
if ( ! pGeomDB->CopyMaterial( nId1, nNewId))
return false ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nCrvCount ;
}
return true ;
}
//-------------------------------------------------------------------------------
static int
MySurfTmSurfTmInters( int nId1, int nId2, int nDestGrpId, double dToler,
int& nPntCount, int& nCrvCount, int& nSrfCount)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGroupGlobFrame( nDestGrpId, frDest))
return GDB_ID_NULL ;
// recupero la prima superficie TriMesh espressa nel riferimento destinazione
SurfLocal Surf1Loc( pGeomDB, nId1, frDest) ;
const ISurfTriMesh* pStm1L = GetSurfTriMesh( Surf1Loc) ;
if ( pStm1L == nullptr)
return GDB_ID_NULL ;
// recupero la seconda superficie TriMesh espressa nel riferimento destinazione
SurfLocal Surf2Loc( pGeomDB, nId2, frDest) ;
const ISurfTriMesh* pStm2L = GetSurfTriMesh( Surf2Loc) ;
if ( pStm2L == nullptr)
return GDB_ID_NULL ;
// eseguo l'intersezione (già espressa nel riferimento destinazione)
PNTVECTOR vPnt ;
BIPNTVECTOR vBpt ;
TRIA3DVECTOR vTria ;
if ( ! IntersSurfTmSurfTm( *pStm1L, *pStm2L, vPnt, vBpt, vTria))
return GDB_ID_NULL ;
// Inserisco il risultato nel DB
int nFirstId = GDB_ID_NULL ;
// Inserisco i punti nel DB
for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) {
// creo il punto
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
if ( IsNull( pGeoPnt))
return GDB_ID_NULL ;
// setto il punto
pGeoPnt->Set( vPnt[i]) ;
// lo inserisco nel DB geometrico
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pGeoPnt)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio il materiale
if ( ! pGeomDB->CopyMaterial( nId1, nNewId))
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nPntCount ;
}
// Inserisco le curve nel DB (dopo averle concatenate)
if ( ! MyChainCurvesForSurfSurfInters( vBpt, pGeomDB, nDestGrpId, nId1, dToler, nFirstId, nCrvCount))
return GDB_ID_NULL ;
// Inserisco i triangoli nel DB (dopo averli uniti in una superficie trimesh)
StmFromTriangleSoup StmFts ;
if ( ! StmFts.Start())
return GDB_ID_NULL ;
for ( int i = 0 ; i < int( vTria.size()) ; ++ i)
// inserisco il triangolo nella nuova superficie
StmFts.AddTriangle( vTria[i]) ;
// valido la superficie e calcolo le adiacenze
if ( ! StmFts.End())
return GDB_ID_NULL ;
// se superficie con triangoli
PtrOwner<ISurfTriMesh> pNewStm( StmFts.GetSurf()) ;
if ( ! IsNull( pNewStm) && pNewStm->GetTriangleCount() > 0) {
// la inserisco nel DB
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrpId, Release( pNewStm)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio il materiale
if ( ! pGeomDB->CopyMaterial( nId1, nNewId))
return GDB_ID_NULL ;
// aggiorno contatori
if ( nFirstId == GDB_ID_NULL)
nFirstId = nNewId ;
++ nSrfCount ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
int
ExeSurfTmSurfTmInters( int nId1, int nId2, int nDestGrpId, double dToler,
int* pnPntCount, int* pnCrvCount, int* pnSrfCount)
{
// eseguo
int nPntCount{ 0}, nCrvCount{ 0}, nSrfCount{ 0} ;
int nFirstId = MySurfTmSurfTmInters( nId1, nId2, nDestGrpId, dToler, nPntCount, nCrvCount, nSrfCount) ;
// aggiorno contatori
if ( nFirstId != GDB_ID_NULL) {
if ( pnPntCount != nullptr)
*pnPntCount = nPntCount ;
if ( pnCrvCount != nullptr)
*pnCrvCount = nCrvCount ;
if ( pnSrfCount != nullptr)
*pnSrfCount = nSrfCount ;
ExeSetModified() ;
}
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtSurfTmSurfTmInters(" + ToString( nId1) + "," +
ToString( nId2) + "," +
ToString( nDestGrpId) + "," +
ToString( dToler) + ")" +
" -- Id1=" + ToString( nFirstId) + ", PntNbr=" + ToString( nPntCount) +
", CrvNbr=" + ToString( nCrvCount) + ", SrfNbr=" + ToString( nSrfCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della prima nuova entità
return nFirstId ;
}
//-------------------------------------------------------------------------------
bool
ExeBBoxOverlap( const BBox3d& bboxA, const Frame3d& frA, const BBox3d& bboxB, const Frame3d& frB)
{
bool bRes = Overlaps( bboxA, frA, bboxB, frB) ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "ExeBBoxOverlap(" + ToString( bboxA) + "," +
ToString( frA) + "," +
ToString( bboxB) + "," +
ToString( frB) + ")" ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco il risultato
return bRes ;
}