EgtGeomKernel 2.5j1 :
- aggiunta funzione SubtractProjectedFacesOnStmFace - modifica funzione GetSilhouette con aggiunta di parametro opzionale.
This commit is contained in:
Binary file not shown.
@@ -401,6 +401,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="RemoveCurveDefects.cpp" />
|
||||
<ClCompile Include="SelfIntersCurve.cpp" />
|
||||
<ClCompile Include="SfrCreate.cpp" />
|
||||
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp" />
|
||||
<ClCompile Include="SurfBezier.cpp" />
|
||||
<ClCompile Include="SurfFlatRegion.cpp" />
|
||||
<ClCompile Include="SurfFlatRegionBooleans.cpp" />
|
||||
@@ -620,6 +621,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="FontOs.h" />
|
||||
<ClInclude Include="AdjustLoops.h" />
|
||||
<ClInclude Include="RemoveCurveDefects.h" />
|
||||
<ClInclude Include="EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="SurfBezier.h" />
|
||||
<ClInclude Include="SurfFlatRegion.h" />
|
||||
<ClInclude Include="TextureData.h" />
|
||||
|
||||
@@ -486,6 +486,9 @@
|
||||
<ClCompile Include="ProjectCurveSurfTm.cpp">
|
||||
<Filter>File di origine\GeoProject</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp">
|
||||
<Filter>File di origine\GeoProject</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1127,6 +1130,9 @@
|
||||
<ClInclude Include="IntersLineCaps.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EGkSubtractProjectedFacesOnStmFace.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
@@ -0,0 +1,733 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2023-2023
|
||||
//----------------------------------------------------------------------------
|
||||
// File : EGkSubtractProjectedFacesOnStmFace.h Data : 26.09.23 Versione : 2.5j1
|
||||
// Contenuto : Dichiarazione della funzione per proiettare facce di TriMesh su una superficie di TriMesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 26.09.23 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkSurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkCurveAux.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include "/EgtDev/Include/EGkSubtractProjectedFacesOnStmFace.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include <array>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Proiezione sottrazione di facce di TriMesh su una faccia di TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ImproveCurve( ICurveComposite* pCrvCompo, const Frame3d frface, const Plane3d plFace, bool& bSkip)
|
||||
{
|
||||
// controllo dei parametri
|
||||
if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid() ||
|
||||
! frface.IsValid())
|
||||
return false ;
|
||||
|
||||
// 1) se la curva ha un'area o un perimetro troppo piccolo, la trascuro
|
||||
double dArea = SQ_EPS_SMALL , dLen = EPS_SMALL ;
|
||||
Plane3d plCrv ;
|
||||
if ( ! pCrvCompo->GetArea( plCrv, dArea) || ! pCrvCompo->GetLength( dLen))
|
||||
return false ;
|
||||
if ( dArea < 50000 * SQ_EPS_SMALL || dLen < 50 * EPS_SMALL) {
|
||||
bSkip = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// 2) Merge per uniformità
|
||||
if ( ! pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL))
|
||||
return false ;
|
||||
|
||||
// 3) Rimuoviamo Spikes o Curve a Z
|
||||
if ( ! pCrvCompo->RemoveSmallDefects( 150 * EPS_SMALL, 2 * ANG_TOL_STD_DEG, true))
|
||||
return false ;
|
||||
|
||||
// 4) Interpoliamo mediante Linee ed Archi
|
||||
PolyArc PA ;
|
||||
pCrvCompo->ToLoc( frface) ; // interpolazione nel piano XY
|
||||
pCrvCompo->ApproxWithArcsEx( 500 * EPS_SMALL, ANG_TOL_STD_DEG, 20.0, PA) ;
|
||||
pCrvCompo->Clear() ;
|
||||
pCrvCompo->FromPolyArc( PA) ;
|
||||
pCrvCompo->ToGlob( frface) ;
|
||||
|
||||
// le curve ricavate dalle TriMesh possono presentare dei piccoli errori di approssimazione che non le rendono
|
||||
// del tutto piane... per sicurezza le proietto sul piano creato
|
||||
double dS, dE ;
|
||||
pCrvCompo->GetDomain( dS, dE) ;
|
||||
PtrOwner<ICurve> pCrv_c( pCrvCompo->CopyParamRange( dS, dE)) ; // da CurveCompo a Curve
|
||||
if ( IsNull( pCrv_c) || ! pCrv_c->IsValid())
|
||||
return false ;
|
||||
PtrOwner<ICurve> pCrv_proj( ProjectCurveOnPlane( *pCrv_c, plFace)) ;
|
||||
// secondo controllo per l'area e il perimetro
|
||||
double dAreaCheck = SQ_EPS_SMALL, dLenCheck = EPS_SMALL ;
|
||||
Plane3d plCheck ;
|
||||
if ( ! IsNull( pCrv_proj) && pCrv_proj->IsClosed()) {
|
||||
pCrv_proj->GetArea( plCheck, dAreaCheck) ;
|
||||
pCrv_proj->GetLength( dLenCheck) ;
|
||||
if ( dAreaCheck < 50000 * SQ_EPS_SMALL || dLenCheck < 50 * EPS_SMALL) {
|
||||
bSkip = true ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
// sostituisco la curva ed esco
|
||||
pCrvCompo->Clear() ;
|
||||
pCrvCompo->CopyFrom( pCrv_proj) ;
|
||||
bSkip = false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetSfrByStm( const ISurfTriMesh* pStm, ISurfFlatRegion* pSfr, const Plane3d plFace)
|
||||
{
|
||||
// controllo validità dei parametri
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || ! plFace.IsValid())
|
||||
return false ;
|
||||
|
||||
// creo un Frame per il sistema di Riferimento Locale
|
||||
Frame3d frFace ; frFace.Set( plFace.GetPoint(), plFace.GetVersN()) ;
|
||||
if ( ! frFace.IsValid())
|
||||
return false ;
|
||||
|
||||
// creo la FlatRegion da resitutiure
|
||||
SurfFlatRegionByContours SrfChunkDef ;
|
||||
|
||||
// recupero i Loop della TriMesh salvandoli in un vettore di PolyLine
|
||||
POLYLINEVECTOR vPl ;
|
||||
pStm->GetLoops( vPl) ;
|
||||
|
||||
// per ogni PolyLine...
|
||||
for ( int i = 0 ; i < ( int)vPl.size() ; ++ i) {
|
||||
// recupero la curva composita
|
||||
PolyLine PL = vPl[i] ;
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
pCrvCompo->FromPolyLine( PL) ;
|
||||
|
||||
// sistemazione varie per la curva ( per creare i loops della FlatRegion)
|
||||
bool bSkip ; // flag per indicare se la curva è accettabile
|
||||
if ( ! ImproveCurve( pCrvCompo, frFace, plFace, bSkip))
|
||||
return false ;
|
||||
if ( ! bSkip)
|
||||
SrfChunkDef.AddCurve( Release( pCrvCompo)) ; // aggiungo la curva
|
||||
}
|
||||
|
||||
// recupero la FlatRegion ( controllandone la validità)
|
||||
PtrOwner<ISurfFlatRegion> pSrfByCurves( SrfChunkDef.GetSurf()) ;
|
||||
if ( IsNull( pSrfByCurves) || ! pSrfByCurves->IsValid() || pSrfByCurves->GetChunkCount() == 0)
|
||||
return true ;
|
||||
|
||||
// restituisco la FlatRegion
|
||||
pSfr->Clear() ;
|
||||
pSfr->CopyFrom( pSrfByCurves) ;
|
||||
return pSfr != nullptr && pSfr->IsValid() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll)
|
||||
{
|
||||
// === controllo se una curva semplice è sufficientemente vicina ad una curva composita ===
|
||||
// controllo dei parametri
|
||||
if (( pCrv == nullptr || pCrvOri == nullptr || dToll < EPS_SMALL))
|
||||
return false ;
|
||||
nStat = 1 ; // 0 -> no overlap | 1 -> overlap
|
||||
|
||||
// prendo nMax + 1 punti sulla curva semplice...
|
||||
const double nMAX = 10.0 ;
|
||||
for ( int i = 0 ; i <= nMAX ; ++i) {
|
||||
double dPar = i / nMAX ;
|
||||
Point3d ptC ; pCrv->GetPointD1D2( dPar, ICurve::FROM_PLUS, ptC) ;
|
||||
if ( ! pCrvOri->IsPointOn( ptC, dToll)) { // se un punto non è vicino, esco
|
||||
nStat = 0 ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
SetTmpPropByOverlap( ICurveComposite* pCrvCheck, const int nInd, const ICurveComposite* pCrvOri, int& nStat,
|
||||
double dToll)
|
||||
{
|
||||
// === Data una sottocurva di una CurveComposite e un'altra composita con le proprietà impostate, spezzo la
|
||||
// sottocurva in tratti di TmpProps uniformi appropriati ===
|
||||
// controllo dei parametri
|
||||
if (( pCrvCheck == nullptr || pCrvOri == nullptr || nInd < 0 || nInd > pCrvCheck->GetCurveCount()
|
||||
|| dToll < EPS_SMALL))
|
||||
return false ;
|
||||
nStat = 1 ; // 0 -> no overlap | 1 -> overlap | 2 -> undefined
|
||||
|
||||
// ricavo la curva da controllare
|
||||
PtrOwner<ICurveComposite> pCrv( GetCurveComposite( pCrvCheck->CopyParamRange( nInd, nInd + 1))) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
|
||||
// controllo se la curva fa overlap ( mediante vicinanza)
|
||||
if ( ! CheckSimpleOverlap( pCrv, pCrvOri, nStat, dToll))
|
||||
return false ;
|
||||
if ( nStat == 0)
|
||||
return true ;
|
||||
|
||||
// ricavo i parametri sulla curva originale di vicinanza
|
||||
double dUS = 0 ; double dUE = 0 ;
|
||||
Point3d ptS ; pCrv->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pCrv->GetEndPoint( ptE) ;
|
||||
pCrvOri->GetParamAtPoint( ptS, dUS, dToll) ;
|
||||
pCrvOri->GetParamAtPoint( ptE, dUE, dToll) ;
|
||||
|
||||
// ricavo una approssimazione adeguata dei paramtri dUS e dUE
|
||||
int nRealDUS = ( int)floor( dUS) ;
|
||||
int nRealDUE = ( int)ceil( dUE) ;
|
||||
if ( ceil( dUS) - dUS < EPS_SMALL)
|
||||
nRealDUS = ( int)ceil( dUS) ;
|
||||
if ( dUE - floor( dUE) < EPS_SMALL)
|
||||
nRealDUE = ( int)floor( dUE) ;
|
||||
if ( nRealDUS == pCrvOri->GetCurveCount())
|
||||
nRealDUS = 0 ;
|
||||
|
||||
// controllo se la vicinanza è relativa a più curve sulla originale con stesse temp prop
|
||||
bool bHasAllSameProp = true ;
|
||||
int nProp_prec ; pCrvOri->GetCurveTempProp( nRealDUS, nProp_prec, 0) ;
|
||||
for ( int u = nRealDUS + 1 ; u < nRealDUE && bHasAllSameProp ; ++ u) {
|
||||
int nProp_act ;
|
||||
pCrvOri->GetCurveTempProp( u, nProp_act, 0) ;
|
||||
if ( nProp_prec != nProp_act)
|
||||
bHasAllSameProp = false ;
|
||||
}
|
||||
if ( bHasAllSameProp) { // se tutte le curve hanno tmpProp uguale...
|
||||
int nCrv = nRealDUS ;
|
||||
int nProp0 = 0 ; pCrvOri->GetCurveTempProp( nCrv, nProp0, 0) ;
|
||||
int nProp1 = 0 ; pCrvOri->GetCurveTempProp( nCrv, nProp1, 1) ;
|
||||
pCrvCheck->SetCurveTempProp( nInd, nProp0, 0) ;
|
||||
//pCrvCheck->SetCurveTempProp( nInd, nProp1, 1) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// copio le sottocurve toccate
|
||||
PtrOwner<ICurveComposite> pCrvOriRange( CloneCurveComposite( pCrvOri)) ;
|
||||
if ( ! pCrvOriRange->TrimStartEndAtParam( floor( dUS), ceil( dUE)))
|
||||
pCrvOriRange->Clear() ;
|
||||
|
||||
if ( ! pCrvOriRange->IsValid()) {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// curva finale da resitutire ( da semplice Curve a CurveComposite)
|
||||
PtrOwner<ICurveComposite> pCrvFinal( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvFinal))
|
||||
return false ;
|
||||
|
||||
// per ogni sottocurva...
|
||||
double dUProjS = 0 ; double dUProjE = 0 ;
|
||||
for ( int u = 0 ; u < pCrvOriRange->GetCurveCount() ; ++ u) {
|
||||
|
||||
Point3d ptCrvOriE ;
|
||||
pCrvOriRange->GetPointD1D2( u + 1, ICurve::FROM_MINUS, ptCrvOriE) ;
|
||||
|
||||
if ( u == 0)
|
||||
dUProjS = 0 ;
|
||||
else
|
||||
dUProjS = dUProjE ;
|
||||
|
||||
if ( u == pCrvOriRange->GetCurveCount() - 1)
|
||||
dUProjE = 1 ;
|
||||
else
|
||||
pCrv->GetParamAtPoint( ptCrvOriE, dUProjE, dToll) ;
|
||||
|
||||
PtrOwner<ICurveComposite> pCrvRange( GetCurveComposite( pCrv->CopyParamRange( dUProjS, dUProjE))) ;
|
||||
if ( ! IsNull( pCrvRange) && pCrvRange->IsValid()) {
|
||||
int nProp0 = 0 ; pCrvOriRange->GetCurveTempProp( u, nProp0, 0) ;
|
||||
int nProp1 = -1 ; pCrvOriRange->GetCurveTempProp( u, nProp1, 1) ;
|
||||
pCrvRange->SetCurveTempProp( 0, nProp0, 0) ;
|
||||
pCrvRange->SetCurveTempProp( 0, nProp1, 1) ;
|
||||
pCrvFinal->AddCurve( Release( pCrvRange)) ;
|
||||
}
|
||||
else {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
// controllo che la CurveComposite ottenuta sia valida e coerente rispetto all'originale ...
|
||||
if ( ! IsNull( pCrvFinal) && pCrvFinal->GetCurveCount() > 0 && pCrvFinal->IsValid()) {
|
||||
Point3d ptSCheck ; Point3d ptECheck ;
|
||||
pCrvFinal->GetStartPoint( ptSCheck) ;
|
||||
pCrvFinal->GetEndPoint( ptECheck) ;
|
||||
if ( ! AreSamePointApprox( ptS, ptSCheck) || ! AreSamePointApprox( ptE, ptECheck))
|
||||
nStat = 2 ;
|
||||
}
|
||||
else
|
||||
nStat = 2 ;
|
||||
|
||||
// ritorno la curva modificata
|
||||
if ( nStat != 2) {
|
||||
pCrvFinal->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ;
|
||||
PtrOwner<ICurveComposite> pCrvToReturn( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvToReturn))
|
||||
return false ;
|
||||
|
||||
// primo tratto di curva della Composita iniziale
|
||||
PtrOwner<ICurveComposite> pCrvA( GetCurveComposite( pCrvCheck->CopyParamRange( 0, nInd))) ;
|
||||
if ( ! IsNull( pCrvA) && pCrvA->GetCurveCount() > 0 && pCrvA->IsValid()) {
|
||||
if ( ! pCrvToReturn->AddCurve( Release( pCrvA))) {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
// tratto corrente di curva con proprietà impostate
|
||||
if ( ! pCrvToReturn->AddCurve( Release( pCrvFinal))) {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// ultimo tratto di curva della Composita iniziale
|
||||
PtrOwner<ICurveComposite> pCrvB( GetCurveComposite( pCrvCheck->CopyParamRange( nInd + 1, pCrvCheck->GetCurveCount()))) ;
|
||||
if ( ! IsNull( pCrvB) && pCrvB->GetCurveCount() > 0 && pCrvB->IsValid())
|
||||
if( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( pCrvToReturn->GetCurveCount() > 0 && pCrvToReturn->IsValid()) {
|
||||
// imposto i parametri originali alla nuova curva
|
||||
double dThick ; pCrvCheck->GetThickness( dThick) ;
|
||||
Vector3d vtExtr ; pCrvCheck->GetExtrusion( vtExtr) ;
|
||||
int nProp0 = pCrvCheck->GetTempProp( 0) ;
|
||||
int nProp1 = pCrvCheck->GetTempProp( 1) ;
|
||||
pCrvCheck->Clear() ;
|
||||
pCrvCheck->AddCurve( Release( pCrvToReturn)) ;
|
||||
pCrvCheck->SetExtrusion( vtExtr ) ;
|
||||
pCrvCheck->SetThickness( dThick) ;
|
||||
pCrvCheck->SetTempProp( nProp0, 0) ;
|
||||
pCrvCheck->SetTempProp( nProp1, 1) ;
|
||||
}
|
||||
else
|
||||
nStat = 2 ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetOCCrvsWithProps( const ISurfTriMesh& StmOrig, int nFaceInd, ICRVCOMPOPOVECTOR& vCrvsWithTmpProps)
|
||||
{
|
||||
// === Data una TriMesh e una sua faccia, stabilire i lati aperti e chiusi dalle adiacenze ===
|
||||
// controllo validità dei parametri
|
||||
if ( ! StmOrig.IsValid())
|
||||
return false ;
|
||||
vCrvsWithTmpProps.clear() ;
|
||||
// recupero i contorni della faccia selezionata
|
||||
POLYLINEVECTOR vPL ;
|
||||
StmOrig.GetFacetLoops( nFaceInd, vPL) ;
|
||||
if ( vPL.empty())
|
||||
return false ;
|
||||
// recupero la normale esterna della faccia
|
||||
Vector3d vtN ;
|
||||
if ( ! StmOrig.GetFacetNormal( nFaceInd, vtN))
|
||||
return false ;
|
||||
// creo la curva a partire dei loop
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; i++) {
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
pCrvCompo->FromPolyLine( vPL[i]) ;
|
||||
if ( ! pCrvCompo->IsValid())
|
||||
return false ;
|
||||
// imposto a 0 tutti i lati della pCrvCompo
|
||||
for ( int u = 0 ; u < pCrvCompo->GetCurveCount() ; ++ u)
|
||||
pCrvCompo->SetCurveTempProp( u, 0, 0) ;
|
||||
// determino eventuali lati aperti e aggiorno proprietà del contorno
|
||||
int nInd = 0 ;
|
||||
double dPar ;
|
||||
bool bFound = vPL[i].GetFirstU( dPar, true) ;
|
||||
while ( bFound) {
|
||||
// recupero il flag
|
||||
int nFlag = int( dPar) ;
|
||||
// se non c'è nulla di adiacente, lato aperto
|
||||
if ( nFlag == SVT_NULL) {
|
||||
pCrvCompo->SetCurveTempProp( nInd, 1, 0) ; // --> lato aperto
|
||||
pCrvCompo->SetCurveTempProp( nInd, -1, 1) ; // --> nessuna faccia adiacente
|
||||
}
|
||||
// altrimenti verifico se la faccia adiacente forma diedro convesso o concavo
|
||||
else {
|
||||
bool bAdjac ;
|
||||
Point3d ptP1, ptP2 ;
|
||||
double dAng ;
|
||||
if ( ! StmOrig.GetFacetsContact( nFaceInd, nFlag, bAdjac, ptP1, ptP2, dAng))
|
||||
dAng = - ANG_RIGHT ;
|
||||
if ( dAng > - EPS_ANG_SMALL) {
|
||||
pCrvCompo->SetCurveTempProp( nInd, 1, 0) ; // --> lato aperto
|
||||
pCrvCompo->SetCurveTempProp( nInd, -1, 1) ; // --> nessuna faccia adiacente
|
||||
}
|
||||
else
|
||||
// salvo come prop 1 la faccia adiacente
|
||||
pCrvCompo->SetCurveTempProp( nInd, nFlag, 1) ; // --> il lato chiuso è 0 per default
|
||||
}
|
||||
// passo al successivo
|
||||
++nInd ;
|
||||
bFound = vPL[i].GetNextU( dPar, true) ;
|
||||
}
|
||||
// assegno l'estrusione dalla normale alla faccia
|
||||
pCrvCompo->SetExtrusion( vtN) ;
|
||||
// unisco le eventuali parti allineate ( mantenendo le proprietà)
|
||||
pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ;
|
||||
// aggiorno la superficie con il loop
|
||||
vCrvsWithTmpProps.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
SewNewStmFacesWithTmpProps( const ISurfFlatRegion& SfrOCCurves, const Plane3d plFace, ISurfTriMesh* pStmFinal)
|
||||
{
|
||||
// controllo dei parametri
|
||||
if ( ! SfrOCCurves.IsValid())
|
||||
return false ;
|
||||
|
||||
// normale dell faccia
|
||||
Vector3d vtN = plFace.GetVersN() ;
|
||||
|
||||
// Creo la TriMesh derivante dai lati chiusi ( estrusione come la normale)
|
||||
// scorro tutti i Loop della FlatRegion cercando le curva che derivano da proiezioni
|
||||
for ( int c = 0 ; c < SfrOCCurves.GetChunkCount() ; ++ c) {
|
||||
for ( int l = 0 ; l < SfrOCCurves.GetLoopCount( c) ; ++ l) {
|
||||
// ricavo il Loop
|
||||
PtrOwner<ICurveComposite> pCrvCompoLoop( ConvertCurveToComposite( SfrOCCurves.GetLoop( c, l))) ;
|
||||
if ( IsNull( pCrvCompoLoop) || ! pCrvCompoLoop->IsValid())
|
||||
return false ;
|
||||
// scorro le sue sottocurve
|
||||
for ( int u = 0 ; u < pCrvCompoLoop->GetCurveCount() ; ++ u) {
|
||||
const ICurve* pCrv_u = pCrvCompoLoop->GetCurve( u) ;
|
||||
if ( pCrv_u == nullptr)
|
||||
return false ;
|
||||
if ( pCrv_u->GetTempProp( 0) == 0) {
|
||||
// se curve chiuse e derivante da una proeizione...
|
||||
PtrOwner<ISurfTriMesh> pStmCurrExtr( GetSurfTriMeshByExtrusion( pCrv_u, - 1 * vtN, false)) ;
|
||||
if ( IsNull( pStmCurrExtr) || ! pStmCurrExtr->IsValid())
|
||||
return false ;
|
||||
// controllo l'orientamento corretto della nuova faccia
|
||||
Vector3d vtNCurr ;
|
||||
if ( ! pStmCurrExtr->GetFacetNormal( 0, vtNCurr))
|
||||
return false ;
|
||||
double dAng ;
|
||||
if ( vtN.GetAngle( vtNCurr, dAng) && dAng > 0)
|
||||
pStmCurrExtr->Invert() ;
|
||||
// aggiungo alla superficie
|
||||
if ( ! pStmFinal->DoSewing( *pStmCurrExtr))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AddClosedEdges( const ISurfTriMesh& StmOrig, int nFaceInd, const ISurfFlatRegion& pSfrOrig,
|
||||
const Plane3d plFace, ISurfTriMesh* pStmFinal)
|
||||
{
|
||||
// controllo validità dei parametri
|
||||
if ( ! StmOrig.IsValid() || pStmFinal == nullptr || ! pStmFinal->IsValid())
|
||||
return false ;
|
||||
|
||||
// creo un vettore di curve con Flag di lato aperto a partire dalla faccia originale
|
||||
ICRVCOMPOPOVECTOR vCrvWithTmpProps ;
|
||||
if ( ! GetOCCrvsWithProps( StmOrig, nFaceInd, vCrvWithTmpProps))
|
||||
return false ;
|
||||
|
||||
// creo la superficie finale da restituire
|
||||
SurfFlatRegionByContours SfrByC ;
|
||||
|
||||
// scorro tutti i loop della FlatRegion della superficie ottenuta dopo la proiezione
|
||||
for ( int c = 0 ; c < pSfrOrig.GetChunkCount() ; ++ c) {
|
||||
for ( int l = 0 ; l < pSfrOrig.GetLoopCount( c) ; ++ l) {
|
||||
// ricavo la curva composita associata al loop corrente
|
||||
PtrOwner<ICurveComposite> pCrvCompoLoop( ConvertCurveToComposite( pSfrOrig.GetLoop( c, l))) ;
|
||||
if ( IsNull( pCrvCompoLoop) || ! pCrvCompoLoop->IsValid())
|
||||
return false ;
|
||||
// scorro ogni curva del loop ottenuto
|
||||
for ( int u = 0 ; u < pCrvCompoLoop->GetCurveCount() ; ++ u) {
|
||||
bool bFound = false ;
|
||||
for ( int i = 0 ; i < int( vCrvWithTmpProps.size()) && !bFound ; ++ i) {
|
||||
int nStat = 0 ;
|
||||
if ( SetTmpPropByOverlap( pCrvCompoLoop, u, vCrvWithTmpProps[i], nStat, 50 * EPS_SMALL) && nStat == 1)
|
||||
bFound = true ;
|
||||
}
|
||||
// se overlap non trovato, allora la curva deriva da una proiezione, quindi chiusa
|
||||
if ( ! bFound) {
|
||||
pCrvCompoLoop->SetCurveTempProp( u, 0, 0) ; // <---- curva chiusa
|
||||
pCrvCompoLoop->SetCurveTempProp( u, -2, 1) ; // <---- derivante da proiezione
|
||||
}
|
||||
}
|
||||
// inserisco la curva con le proprietà definite
|
||||
SfrByC.AddCurve( Release( pCrvCompoLoop)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// recupero la FlatRegion con le curve impostate
|
||||
PtrOwner<ISurfFlatRegion> pSfrWithTmpProps( SfrByC.GetSurf()) ;
|
||||
if ( IsNull( pSfrWithTmpProps) || ! pSfrWithTmpProps->IsValid())
|
||||
return false ;
|
||||
|
||||
// creo la TriMesh finale da restituire ed esco
|
||||
return SewNewStmFacesWithTmpProps( *pSfrWithTmpProps, plFace, pStmFinal) ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SubtractProjectedFacesOnStmFace( const ISurfTriMesh& Stm, int nFaceInd,
|
||||
ISURFTMPOVECTOR& vStmOthers, INTVECTOR& vFIndOthers, bool bOCFlag,
|
||||
bool& bExistProjection, ISurfTriMesh*& pStmRes, int& nNewFaceNbr)
|
||||
{
|
||||
// verifico validità della superificie originale
|
||||
if ( ! Stm.IsValid())
|
||||
return false ;
|
||||
|
||||
// ricavo la faccia su cui togliere le proiezioni
|
||||
PtrOwner<ISurfTriMesh> pStm_face( Stm.CloneFacet( nFaceInd)) ;
|
||||
if ( IsNull( pStm_face) || ! pStm_face->IsValid())
|
||||
return false ;
|
||||
|
||||
// imposto valori di ritorno di default
|
||||
bExistProjection = false ;
|
||||
nNewFaceNbr = 1 ;
|
||||
pStmRes = CreateSurfTriMesh() ;
|
||||
pStmRes->CopyFrom( pStm_face) ;
|
||||
|
||||
// dimensione dei vettori passati come parametri
|
||||
int nVStm_size = ( int)vStmOthers.size() ;
|
||||
int nVId_size = ( int)vFIndOthers.size() ;
|
||||
// se vettori di dimensioni diverse -> incoerenza
|
||||
if ( nVStm_size != nVId_size)
|
||||
return false ;
|
||||
// se entrambi sono vuoti, alora considero di proiettare tutte le altre facce della TriMesh
|
||||
bool bIsSize0 = ( nVStm_size == 0) ;
|
||||
if ( bIsSize0) {
|
||||
// se entrambi i vettori sono vuoti, allora considero da proiettare tutte le altre facce della TriMesh
|
||||
PtrOwner<ISurfTriMesh> pStmNoSelFace( Stm.Clone()) ;
|
||||
if ( IsNull( pStmNoSelFace) || ! pStmNoSelFace->IsValid())
|
||||
return false ;
|
||||
// se la superficie ha solo una faccia e cerco di toglierla, allora non devo proiettare nulla...
|
||||
if ( pStmNoSelFace->GetFacetCount() == 1)
|
||||
return true ;
|
||||
// rimuovo la faccia da proiettare
|
||||
if ( ! pStmNoSelFace->RemoveFacet( nFaceInd))
|
||||
return false ;
|
||||
// controllo la validità di questa operazione
|
||||
if ( IsNull( pStmNoSelFace) || ! pStmNoSelFace->IsValid())
|
||||
return false ;
|
||||
// modifico il vettore delle TriMesh e delle loro facce
|
||||
vStmOthers.emplace_back( Release( pStmNoSelFace)) ;
|
||||
nVStm_size = 1 ;
|
||||
// NB. E' adottata questa strategia per evitare di proiettare un numero elevato di facce dovuto alla presenza
|
||||
// di archi; calcolo la GetSilhouette dell'intero contorno e non come unione delle singole facce proiettate
|
||||
}
|
||||
|
||||
// creo il sistema di riferimento ( inerente alla faccia selezionata)
|
||||
Point3d ptORIG ;
|
||||
Vector3d vtN ;
|
||||
if ( ! pStm_face->GetCentroid( ptORIG) || // ricavo origine
|
||||
! pStm_face->GetFacetNormal( 0, vtN)) // ricavo normale
|
||||
return false ;
|
||||
Frame3d frFace ; frFace.Set( ptORIG, vtN) ;
|
||||
if ( ! frFace.IsValid())
|
||||
return false ;
|
||||
|
||||
// creo un piano passante per la faccia selezionata ( di normale inversa per il taglio)
|
||||
// ( tutto ciò che sta nel semipiano negativo della faccia selezionata, non viene proiettato ma tagliato)
|
||||
Plane3d plFace ;
|
||||
plFace.Set( ptORIG, -vtN) ;
|
||||
if ( ! plFace.IsValid())
|
||||
return false ;
|
||||
|
||||
// superficie finale della proeizione
|
||||
PtrOwner<ISurfFlatRegion> pSfr_proj( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfr_proj))
|
||||
return false ;
|
||||
bool bExistProj = false ; // flag per indicare se almeno un triangolo è stato proiettato
|
||||
|
||||
// scorro le parti di superfici da proiettare...
|
||||
for ( int t = 0 ; t < nVStm_size ; ++ t) {
|
||||
// proiezione corrente
|
||||
PtrOwner<ISurfTriMesh> pStm_CurrProj( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStm_CurrProj))
|
||||
return false ;
|
||||
// *** se sono stati passati alla funzione vettori non vuoti, allora pStm_CurrProj è la faccia
|
||||
// *** corrente da proiettare
|
||||
if ( ! bIsSize0) {
|
||||
// se la faccia da proiettare è perpendicolare alla faccia selezionata, non la considero
|
||||
Vector3d vtN_curr ;
|
||||
if ( ! vStmOthers[t]->GetFacetNormal( vFIndOthers[t], vtN_curr) ||
|
||||
abs( vtN_curr * vtN) < 5 * EPS_SMALL) // <--- | prodotto scalare | < 5 * EPS_SMALL
|
||||
continue ;
|
||||
// recupero la faccia da proiettare ( controllando la sua validità)
|
||||
pStm_CurrProj.Set( vStmOthers[t]->CloneFacet( vFIndOthers[t])) ;
|
||||
if ( IsNull( pStm_CurrProj) || ! pStm_CurrProj->IsValid())
|
||||
return false ;
|
||||
}
|
||||
// *** se sono stati passati alla funzione vettori vuoti allora pStm_CurrProj contiene tutta la TriMesh
|
||||
// *** meno la faccia scelta
|
||||
else {
|
||||
PtrOwner<ISurfTriMesh> pStmForProj( CloneSurfTriMesh( vStmOthers[0])) ;
|
||||
PtrOwner<ISurfTriMesh> pStmForProj_noPerpFaces( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmForProj) || ! pStmForProj->IsValid() || IsNull( pStmForProj_noPerpFaces))
|
||||
return false ;
|
||||
StmFromTriangleSoup StmFts ;
|
||||
StmFts.Start() ;
|
||||
// rimuovo le facce perpendicolari
|
||||
for ( int f = 0 ; f < pStmForProj->GetFacetCount() ; ++ f) {
|
||||
Vector3d vtN_curr ;
|
||||
if ( pStmForProj->GetFacetNormal( f, vtN_curr) && abs( vtN_curr * vtN) > 5 * EPS_SMALL) {
|
||||
PtrOwner<ISurfTriMesh> pStm_face( pStmForProj->CloneFacet( f)) ;
|
||||
if ( IsNull( pStm_face) || ! pStm_face->IsValid())
|
||||
return false ;
|
||||
Triangle3d Tria ;
|
||||
int nT = pStm_face->GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// inserisco il triangolo nella nuova superficie
|
||||
StmFts.AddTriangle( Tria) ;
|
||||
// passo al triangolo successivo
|
||||
nT = pStm_face->GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
StmFts.End() ;
|
||||
pStmForProj_noPerpFaces.Set( StmFts.GetSurf()) ;
|
||||
// se la superficie senza le facce perpendicolari non è valida, allora ho finito
|
||||
if ( ! pStmForProj_noPerpFaces->IsValid())
|
||||
return true ;
|
||||
// sistemo
|
||||
pStmForProj_noPerpFaces->Repair() ;
|
||||
// sostituisco
|
||||
pStm_CurrProj.Set( Release( pStmForProj_noPerpFaces)) ;
|
||||
}
|
||||
|
||||
// taglio la superficie con il piano creato ( la proiezione esclude le parti nel semipiano negativo)
|
||||
if ( ! pStm_CurrProj->Cut( plFace, true))
|
||||
return false ;
|
||||
// controllo la validità di questa operazione ( la faccia potrebbe essere tutta nel semipiano negativo)
|
||||
if ( IsNull( pStm_CurrProj) || ! pStm_CurrProj->IsValid() || pStm_CurrProj->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// recupero la PolyLine della Silhouette
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pStm_CurrProj->GetSilhouette( vtN, 100 * EPS_SMALL, vPL, true))
|
||||
return false ;
|
||||
// converto le curve in composite
|
||||
// NB. Potrei ottenere più curve, quindi creo la FlatRegion associata
|
||||
SurfFlatRegionByContours sfrBCProj_face ;
|
||||
bool bValidCurrProj = false ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo))
|
||||
return false ;
|
||||
pCrvCompo->FromPolyLine( vPL[i]) ;
|
||||
bool bSkip = true ; // flag per indicare se la curva è valida
|
||||
if ( ! ImproveCurve( pCrvCompo, frFace, plFace, bSkip))
|
||||
return false ;
|
||||
// se curva ammissibile, creo la sua FlatRegion
|
||||
if ( ! bSkip) {
|
||||
bValidCurrProj = true ;
|
||||
sfrBCProj_face.AddCurve( Release( pCrvCompo)) ;
|
||||
bExistProj = true ;
|
||||
}
|
||||
}
|
||||
// se proeizione non valida, allora passo all'entità successiva
|
||||
if ( ! bValidCurrProj)
|
||||
continue ;
|
||||
// ricavo la FlatRegion associata alla proiezione delle faccia
|
||||
PtrOwner<ISurfFlatRegion> pSfr_proj_faceCurr( sfrBCProj_face.GetSurf()) ;
|
||||
if ( IsNull( pSfr_proj_faceCurr) || ! pSfr_proj_faceCurr->IsValid())
|
||||
return false ;
|
||||
// inverto se necessario
|
||||
if ( AreOppositeVectorApprox( pSfr_proj_faceCurr->GetNormVersor(), vtN))
|
||||
pSfr_proj_faceCurr->Invert() ;
|
||||
// la sommo alla regione di proeizione globale
|
||||
if ( ! pSfr_proj->IsValid() || pSfr_proj->GetChunkCount() == 0)
|
||||
pSfr_proj.Set( Release( pSfr_proj_faceCurr)) ;
|
||||
else
|
||||
if ( ! pSfr_proj->Add( *pSfr_proj_faceCurr))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se non c'è nulla d proiettare e flag bOCFlag false, allora esco
|
||||
if ( ! bExistProj && ! bOCFlag)
|
||||
return true ;
|
||||
|
||||
// FlatRegion associata alla faccia della TriMesh selezionata
|
||||
PtrOwner<ISurfFlatRegion> pSfr_face( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfr_face) || ! GetSfrByStm( pStm_face, pSfr_face, plFace) || ! pSfr_face->IsValid())
|
||||
return false ;
|
||||
// per sicurezza controllo la coerenza con le normali ( per fare la sottrazione)
|
||||
if ( AreOppositeVectorApprox( pSfr_face->GetNormVersor(), vtN))
|
||||
pSfr_face->Invert() ;
|
||||
|
||||
// superficie finale da restituire
|
||||
PtrOwner<ISurfTriMesh> pStm_final( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStm_final))
|
||||
return false ;
|
||||
|
||||
// *** se la proiezione esiste...
|
||||
if ( bExistProj) {
|
||||
// controllo validità della FlatRegion di proiezione globale
|
||||
if ( IsNull( pSfr_proj) || ! pSfr_proj->IsValid())
|
||||
return false ;
|
||||
// ho una proiezione ...
|
||||
bExistProjection = true ;
|
||||
// per sicurezza controllo la coerenza con le normali ( per fare la sottrazione)
|
||||
if ( AreOppositeVectorApprox( pSfr_proj->GetNormVersor(), vtN))
|
||||
pSfr_proj->Invert() ;
|
||||
// sottraggo le FlatRegions ( FlatRegion della faccia selezionata \ FlatRegion proiezione)
|
||||
if ( ! pSfr_face->Subtract( *pSfr_proj))
|
||||
return false ;
|
||||
// controllo validità della sottrazione
|
||||
if ( IsNull( pSfr_face) || ! pSfr_face->IsValid() || pSfr_face->GetChunkCount() == 0) {
|
||||
// la proiezione copre completamente la faccia selezionata
|
||||
delete( pStmRes) ;
|
||||
pStmRes = nullptr ;
|
||||
nNewFaceNbr = 0 ;
|
||||
return true ;
|
||||
}
|
||||
// aggiorno il numero di facce creato
|
||||
nNewFaceNbr = pSfr_face->GetChunkCount() ;
|
||||
}
|
||||
|
||||
// riconverto la FlatRegion in TriMesh ( per restituirla)
|
||||
const ISurfTriMesh* pStm_tmp = pSfr_face->GetAuxSurf() ;
|
||||
if ( pStm_tmp == nullptr || ! pStm_tmp->IsValid())
|
||||
return false ;
|
||||
pStm_final.Set( pStm_tmp->Clone()) ;
|
||||
if ( IsNull( pStm_final) || ! pStm_final->IsValid())
|
||||
return false ;
|
||||
|
||||
// se richiesto aggiugno delle facce sui lati chiusi
|
||||
if ( bOCFlag)
|
||||
if ( ! AddClosedEdges( Stm, nFaceInd, *pSfr_face, plFace, pStm_final))
|
||||
return false ;
|
||||
|
||||
// assegno i valori di ritorno della funzione ed esco
|
||||
pStmRes->CopyFrom( pStm_final) ;
|
||||
return pStmRes->IsValid() && pStmRes->GetTriangleCount() > 0 ;
|
||||
}
|
||||
|
||||
+6
-3
@@ -1069,7 +1069,7 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const
|
||||
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria) const
|
||||
{
|
||||
// Verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1166,17 +1166,20 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
int nT = GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// verifico la normale e il triangolo proiettato
|
||||
if ( Tria.GetN() * vtVers > EPS_ZERO &&
|
||||
if ( ( ( bAllTria && abs( Tria.GetN() * vtVers) > EPS_ZERO) ||
|
||||
( ! bAllTria && Tria.GetN() * vtVers > EPS_ZERO)) &&
|
||||
Tria.Scale( frOCS, 1, 1, 0) && Tria.GetSqMinHeight() > SQ_EPS_SMALL) {
|
||||
PtrOwner<ISurfFlatRegion> pSfrTria( GetSurfFlatRegionFromTriangle( Tria)) ;
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// passo al successivo
|
||||
nT = GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
|
||||
+1
-1
@@ -261,7 +261,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
|
||||
SurfTriMesh* CloneTriangle( int nT) const override ;
|
||||
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
|
||||
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const override ;
|
||||
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||
int GetFacetCount( void) const override ;
|
||||
int GetFacetSize( void) const override
|
||||
{ return int( m_vFacet.size()) ; }
|
||||
|
||||
Reference in New Issue
Block a user