Files
EgtGeomKernel/SurfFlatRegion.cpp
T
Dario Sassi f4b88af3e1 EgtGeomKernel 1.6h2 :
- aggiunte Regioni (SurfFlatRegion) e prime funzionalità relative
- corretti Intervals per Add
- corretta CalcPointParamPosiz per archi che in realtà sono circonferenze.
2015-08-07 10:45:40 +00:00

834 lines
26 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : SurfFlatRegion.cpp Data : 05.08.15 Versione : 1.6h2
// Contenuto : Implementazione della classe Surface FlatRegion.
//
//
//
// Modifiche : 05.08.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfFlatRegion.h"
#include "GeoObjFactory.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "CurveAux.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkUiUnits.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
GEOOBJ_REGISTER( SRF_FLATRGN, NGE_S_FRG, SurfFlatRegion) ;
//----------------------------------------------------------------------------
SurfFlatRegion::SurfFlatRegion( void)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_pExtLoop( nullptr), m_nTempProp(), m_Iter( m_vpIntLoop.end())
{
}
//----------------------------------------------------------------------------
SurfFlatRegion::~SurfFlatRegion( void)
{
Clear() ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Clear( void)
{
if ( m_pSTM != nullptr)
delete( m_pSTM) ;
m_pSTM = nullptr ;
m_nStatus = TO_VERIFY ;
m_frF.Reset() ;
// ciclo di pulizia
if ( m_pExtLoop != nullptr)
delete( m_pExtLoop) ;
m_pExtLoop = nullptr ;
for ( auto Iter = m_vpIntLoop.begin() ; Iter != m_vpIntLoop.end() ; ++Iter)
delete (*Iter) ;
m_vpIntLoop.clear() ;
m_nTempProp = 0 ;
m_Iter = m_vpIntLoop.end() ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::SetExtLoop( const ICurve& cCrv)
{
// verifico validità curva
if ( &cCrv == nullptr)
return false ;
// creo una copia della curva
ICurve* pCrv( cCrv.Clone()) ;
if ( pCrv == nullptr)
return false ;
// procedo
return SetExtLoop( pCrv) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::SetExtLoop( ICurve* pCrv)
{
// resetto tutto
Clear() ;
// acquisisco la curva
PtrOwner<ICurve> pMyCrv( pCrv) ;
if ( IsNull( pMyCrv))
return false ;
// verifico sia chiusa
if ( ! pMyCrv->IsClosed())
return false ;
// verifico sia piana
Plane3d plPlane ;
if ( ! pMyCrv->IsFlat( plPlane))
return false ;
// assegno il riferimento intrinseco
if ( ! m_frF.Set( ORIG + plPlane.vtN * plPlane.dDist, plPlane.vtN))
return false ;
// porto la curva nel riferimento intrinseco
if ( ! pMyCrv->ToLoc( m_frF))
return false ;
// verifico non abbia auto-intersezioni
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetNumInters() > 0)
return false ;
// sistemo il senso di rotazione (deve essere CCW -> area > 0)
double dArea ;
if ( ! pMyCrv->GetAreaXY( dArea) || fabs( dArea) < 100 * EPS_SMALL * EPS_SMALL)
return false ;
if ( dArea < 0)
pMyCrv->Invert() ;
// assegno la curva al loop esterno
m_pExtLoop = Release( pMyCrv) ;
m_nStatus = OK ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::AddIntLoop( const ICurve& cCrv)
{
// verifico validità curva
if ( &cCrv == nullptr)
return false ;
// creo una copia della curva
ICurve* pCrv( cCrv.Clone()) ;
if ( pCrv == nullptr)
return false ;
// procedo
return AddIntLoop( pCrv) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::AddIntLoop( ICurve* pCrv)
{
// acquisisco la curva
PtrOwner<ICurve> pMyCrv( pCrv) ;
if ( IsNull( pMyCrv))
return false ;
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// verifico sia chiusa
if ( ! pMyCrv->IsClosed())
return false ;
// porto la curva nel riferimento intrinseco
if ( ! pMyCrv->ToLoc( m_frF))
return false ;
// verifico sia piana e il piano coincida con quello XY intrinseco
Plane3d plPlane ;
if ( ! pMyCrv->IsFlat( plPlane))
return false ;
if ( ! plPlane.vtN.IsZplus() && ! plPlane.vtN.IsZminus() && fabs( plPlane.dDist) > EPS_SMALL)
return false ;
// verifico non abbia auto-intersezioni
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetNumInters() > 0)
return false ;
// verifico non abbia intersezioni e sia interna al loop esterno
IntersCurveCurve ccInt( *pMyCrv, *m_pExtLoop) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetNumInters() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
return false ;
// verifico non abbia intersezioni con eventuali altri loop interni
for ( auto& pIntLoop : m_vpIntLoop) {
IntersCurveCurve ccInt( *pMyCrv, *pIntLoop) ;
if ( ccInt.GetNumInters() > 0)
return false ;
}
// sistemo il senso di rotazione (deve essere CW -> area < 0)
double dArea ;
if ( ! pMyCrv->GetAreaXY( dArea) || fabs( dArea) < 100 * EPS_SMALL * EPS_SMALL)
return false ;
if ( dArea > 0)
pMyCrv->Invert() ;
// aggiungo la curva all'elenco dei loop interni
m_vpIntLoop.push_back( Release( pMyCrv)) ;
return true ;
}
//----------------------------------------------------------------------------
SurfFlatRegion*
SurfFlatRegion::Clone( void) const
{
// alloco oggetto
SurfFlatRegion* pSfr = new(nothrow) SurfFlatRegion ;
if ( pSfr != nullptr) {
if ( ! pSfr->CopyFrom( *this)) {
delete pSfr ;
return nullptr ;
}
}
return pSfr ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::CopyFrom( const IGeoObj* pGObjSrc)
{
const SurfFlatRegion* pSfr = dynamic_cast<const SurfFlatRegion*>( pGObjSrc) ;
if ( pSfr == nullptr)
return false ;
return CopyFrom( *pSfr) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::CopyFrom( const SurfFlatRegion& sfrSrc)
{
if ( &sfrSrc == this)
return true ;
Clear() ;
if ( sfrSrc.m_pSTM != nullptr)
m_pSTM = sfrSrc.m_pSTM->Clone() ;
m_frF = sfrSrc.m_frF ;
if ( sfrSrc.m_pExtLoop != nullptr)
m_pExtLoop = sfrSrc.m_pExtLoop->Clone() ;
for ( auto& pIntLoop : sfrSrc.m_vpIntLoop) {
ICurve* pCrv = pIntLoop->Clone() ;
if ( pCrv == nullptr)
return false ;
m_vpIntLoop.push_back( pCrv) ;
}
m_nTempProp = sfrSrc.m_nTempProp ;
m_nStatus = sfrSrc.m_nStatus ;
return ( m_nStatus == OK && m_pExtLoop != nullptr) ;
}
//----------------------------------------------------------------------------
GeoObjType
SurfFlatRegion::GetType( void) const
{
return static_cast<GeoObjType>( GEOOBJ_GETTYPE( SurfFlatRegion)) ;
}
//----------------------------------------------------------------------------
const string&
SurfFlatRegion::GetTitle( void) const
{
static const string sTitle = "FlatRegion" ;
return sTitle ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Dump( string& sOut, bool bMM, const char* szNewLine) const
{
// verifico validità regione
if ( m_nStatus != OK)
sOut += string( "Status=Invalid") + szNewLine ;
// area
double dArea ;
if ( GetArea( dArea))
sOut += "Area=" + ToString( GetAreaInUiUnits( dArea, bMM),1) + szNewLine ;
// riferimento intrinseco : origine, VersoreX, VersoreY, VersoreZ
sOut += "O(" + ToString( GetInUiUnits( m_frF.Orig(), bMM)) + ")" + szNewLine ;
sOut += "VX(" + ToString( m_frF.VersX()) + ")" + szNewLine ;
sOut += "VY(" + ToString( m_frF.VersY()) + ")" + szNewLine ;
sOut += "VZ(" + ToString( m_frF.VersZ()) + ")" + szNewLine ;
// loop esterno
if ( m_pExtLoop != nullptr) {
sOut += string( "External Loop :") + szNewLine ;
m_pExtLoop->Dump( sOut, bMM, szNewLine) ;
}
else
sOut += string( "External Loop Invalid") + szNewLine ;
// loop interni
sOut += "Internal Loops=" + ToString( GetIntLoopNumber()) + szNewLine ;
int i = 0 ;
for ( auto& pIntLoop : m_vpIntLoop) {
sOut += "##" + ToString( ++i) + szNewLine ;
pIntLoop->Dump( sOut, bMM, szNewLine) ;
}
return true ;
}
//----------------------------------------------------------------------------
int
SurfFlatRegion::GetNgeId( void) const
{
return GEOOBJ_GETNGEID( SurfFlatRegion) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Save( NgeWriter& ngeOut) const
{
// frame
if ( ! ngeOut.WriteFrame( m_frF, ";", true))
return false ;
// numero di loops (esterno + interni)
if ( ! ngeOut.WriteInt( 1 + int( m_vpIntLoop.size()), nullptr, true))
return false ;
// ciclo sui loop
int i = 0 ;
const ICurve* pCrv = GetMyLoop( i) ;
while ( pCrv != nullptr) {
// recupero il gestore di lettura/scrittura della curva
const IGeoObjRW* pCSmplRW = dynamic_cast<const IGeoObjRW*>( pCrv) ;
if ( pCSmplRW == nullptr)
return false ;
// emetto il tipo della curva
if ( ! ngeOut.WriteKey( pCSmplRW->GetNgeId()))
return false ;
// assegno ed emetto il nome della curva
string sCrvName = "##" + ToString( i) ;
if ( ! ngeOut.WriteString( sCrvName, nullptr, true))
return false ;
// salvo la curva
if ( ! pCSmplRW->Save( ngeOut))
return false ;
// passo alla successiva
++ i ;
pCrv = GetMyLoop( i) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Load( NgeReader& ngeIn)
{
Clear() ;
// leggo i dati del riferimento
if ( ! ngeIn.ReadFrame( m_frF, ";", true))
return false ;
// leggo la prossima linea ( 1 parametro)
// recupero il numero di curve componenti
int nCounter ;
if ( ! ngeIn.ReadInt( nCounter, nullptr, true))
return false ;
// leggo le curve componenti
for ( int i = 0 ; i < nCounter ; ++ i) {
// recupero la prossima linea (con il tipo di oggetto)
int nNgeId ;
if ( ! ngeIn.ReadKey( nNgeId))
return false ;
// creo l'oggetto
int nType = GEOOBJ_NGEIDTOTYPE( nNgeId) ;
IGeoObj* pGeoO = GEOOBJ_CREATE( nType) ;
if ( pGeoO == nullptr)
return false ;
// recupero la linea con il nome
string sName ;
int j ;
bool bOk = ngeIn.ReadString( sName, nullptr, true) &&
FromString( sName.substr(2), j) && i == j ;
// ne leggo i dati
IGeoObjRW* pGObjRW = dynamic_cast<IGeoObjRW*>( pGeoO) ;
bOk = bOk && ( pGObjRW != nullptr && pGObjRW->Load( ngeIn)) ;
// verifico sia una curva
ICurve* pCrv = ::GetCurve( pGeoO) ;
bOk = bOk && ( pCrv != nullptr) ;
// aggiungo questa curva
if ( bOk) {
if ( i == 0)
m_pExtLoop = pCrv ;
else
m_vpIntLoop.push_back( pCrv) ;
}
// se errore
if ( ! bOk)
return false ;
}
// aggiorno stato
m_nStatus = OK ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// è il bounding box del loop esterno
return m_pExtLoop->GetBBox( m_frF, b3Loc, nFlag) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// frame composito
Frame3d frCompo = m_frF * frRef ;
// è il bounding box del loop esterno
return m_pExtLoop->GetBBox( frCompo, b3Ref, nFlag) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Translate( const Vector3d& vtMove)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// traslo il riferimento
m_frF.Translate( vtMove) ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// ruoto il riferimento
return m_frF.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// se scalatura non uniforme, sostituisco eventuali archi con curve di Bezier
if ( fabs( dCoeffX - dCoeffY) > EPS_SMALL || fabs( dCoeffX - dCoeffZ) > EPS_SMALL) {
if ( ! ConvertArcsToBezierCurves())
return false ;
}
// parziale scalatura del riferimento (non può essere completa)
Frame3d frTrasf = m_frF ;
m_frF.PseudoScale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
// porto i loop nel nuovo riferimento, senza modificarne la geometria in globale
frTrasf.ToLoc( m_frF) ;
m_pExtLoop->ToGlob( frTrasf) ;
for ( auto& pIntLoop : m_vpIntLoop)
pIntLoop->ToGlob( frTrasf) ;
// porto il riferimento di scalatura nel nuovo riferimento del gruppo
Frame3d frRefLoc = frRef ;
frRefLoc.ToLoc( m_frF) ;
// ciclo sui loop
bool bOk = m_pExtLoop->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ) ;
for ( auto& pIntLoop : m_vpIntLoop) {
if ( ! pIntLoop->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ))
bOk = false ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// parziale mirror del riferimento (non può essere completa)
Frame3d frTrasf = m_frF ;
m_frF.PseudoMirror( ptOn, vtNorm) ;
// porto i loop nel nuovo riferimento, senza modificarne la geometria in globale
frTrasf.ToLoc( m_frF) ;
m_pExtLoop->ToGlob( frTrasf) ;
for ( auto& pIntLoop : m_vpIntLoop)
pIntLoop->ToGlob( frTrasf) ;
// porto i dati del piano di mirror nel riferimento del gruppo
Point3d ptOnLoc = ptOn ;
ptOnLoc.ToLoc( m_frF) ;
Vector3d vtNormLoc = vtNorm ;
vtNormLoc.ToLoc( m_frF) ;
// ciclo sui loop (mirror + invert)
bool bOk = m_pExtLoop->Mirror( ptOnLoc, vtNormLoc) && m_pExtLoop->Invert() ;
for ( auto& pIntLoop : m_vpIntLoop) {
if ( ! pIntLoop->Mirror( ptOnLoc, vtNormLoc) || ! pIntLoop->Invert())
bOk = false ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Invert( void)
{
// E' un mirror rispetto al piano XY del riferimento intrinseco
return Mirror( m_frF.Orig(), m_frF.VersZ()) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// se il piano di scorrimento non coincide con XY intrinseco, converto eventuali archi in curve di Bezier
if ( ! AreSameOrOppositeVectorExact( m_frF.VersZ(), vtNorm)) {
if ( ! ConvertArcsToBezierCurves())
return false ;
}
// parziale scorrimento del riferimento (non può essere completa)
Frame3d frTrasf = m_frF ;
m_frF.PseudoShear( ptOn, vtNorm, vtDir, dCoeff) ;
// porto i loop nel nuovo riferimento, senza modificarne la geometria in globale
frTrasf.ToLoc( m_frF) ;
m_pExtLoop->ToGlob( frTrasf) ;
for ( auto& pIntLoop : m_vpIntLoop)
pIntLoop->ToGlob( frTrasf) ;
// porto i dati di scorrimento nel riferimento del gruppo
Point3d ptOnLoc = ptOn ;
ptOnLoc.ToLoc( m_frF) ;
Vector3d vtNormLoc = vtNorm ;
vtNormLoc.ToLoc( m_frF) ;
Vector3d vtDirLoc = vtDir ;
vtDirLoc.ToLoc( m_frF) ;
// ciclo sugli oggetti
bool bOk = m_pExtLoop->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff) ;
for ( auto& pIntLoop : m_vpIntLoop) {
if ( ! pIntLoop->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff))
bOk = false ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::ConvertArcsToBezierCurves( void)
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// loop esterno
if ( m_pExtLoop->GetType() == CRV_ARC) {
ICurve* pCrvNew = ArcToBezierCurve( m_pExtLoop) ;
if ( pCrvNew == nullptr)
return false ;
delete m_pExtLoop ;
m_pExtLoop = pCrvNew ;
}
// eventuali loop interni
for ( auto& pIntLoop : m_vpIntLoop) {
if ( pIntLoop->GetType() == CRV_ARC) {
ICurve* pCrvNew = ArcToBezierCurve( pIntLoop) ;
if ( pCrvNew == nullptr)
return false ;
delete pIntLoop ;
pIntLoop = pCrvNew ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::ToGlob( const Frame3d& frRef)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// trasformo il riferimento
return m_frF.ToGlob( frRef) ; ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::ToLoc( const Frame3d& frRef)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// trasformo il riferimento
return m_frF.ToLoc( frRef) ; ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// trasformo il riferimento
return m_frF.LocToLoc( frOri, frDest) ; ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetArea( double& dArea) const
{
// controllo parametro di ritorno
if ( &dArea == nullptr)
return false ;
// inizio con area nulla
dArea = 0 ;
// la regione deve essere validata
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// sommo l'area di tutti i loop (gli interni hanno area negativa)
bool bOk = m_pExtLoop->GetAreaXY( dArea) ;
for ( auto& pIntLoop : m_vpIntLoop) {
double dTemp ;
if ( pIntLoop->GetAreaXY( dTemp))
dArea += dTemp ;
else
bOk = false ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCentroid( Point3d& ptCen) const
{
// controllo parametro di ritorno
if ( &ptCen == nullptr)
return false ;
// la regione deve essere validata
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// determino il centroide del solo loop esterno
return m_pExtLoop->GetCentroid( ptCen) ;
}
//----------------------------------------------------------------------------
ICurve*
SurfFlatRegion::GetMyLoop( int nLoop) const
{
// la regione deve essere validata
if ( m_nStatus != OK)
return nullptr ;
// se esterno
if ( nLoop == 0)
return m_pExtLoop ;
// altrimenti interno, verifico che l'indice sia nei limiti
if ( nLoop < 1 || nLoop > int( m_vpIntLoop.size()))
return nullptr ;
else
return m_vpIntLoop[nLoop-1] ;
}
//----------------------------------------------------------------------------
ICurve*
SurfFlatRegion::GetLoop( int nLoop) const
{
// recupero il loop nel riferimento intrinseco
const ICurve* pMyCrv = GetMyLoop( nLoop) ;
if ( pMyCrv == nullptr)
return nullptr ;
// ne faccio una copia
ICurve* pCrv = pMyCrv->Clone() ;
if ( pCrv == nullptr)
return nullptr ;
// la porto nel riferimento in cui è inserito l'oggetto
pCrv->ToGlob( m_frF) ;
return pCrv ;
}
//----------------------------------------------------------------------------
const ISurfTriMesh*
SurfFlatRegion::GetAuxSurf( void) const
{
// la superficie deve essere validata
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// se già calcolata, la restituisco
if ( m_pSTM != nullptr)
return m_pSTM ;
// la calcolo
// calcolo le polilinee che approssimano i loop
POLYLINEVECTOR vPL ;
vPL.resize( 1 + int( m_vpIntLoop.size())) ;
int i = - 1 ;
if ( ! m_pExtLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL[++i]))
return nullptr ;
for ( auto& pIntLoop : m_vpIntLoop) {
if ( ! pIntLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL[++i]))
return nullptr ;
}
// porto le polilinee in globale al riferimento intrinseco
for ( auto& PL : vPL)
PL.ToGlob( m_frF) ;
// creo, setto la superficie trimesh ed elimino punti ripetuti
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL) || ! pSTM->DoCompacting())
return nullptr ;
// la salvo
m_pSTM = Release( pSTM) ;
return m_pSTM ;
}
//----------------------------------------------------------------------------
void
SurfFlatRegion::ResetAuxSurf( void) const
{
if ( m_pSTM != nullptr)
delete( m_pSTM) ;
m_pSTM = nullptr ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
{
// verifico lo stato
if ( m_nStatus != OK || m_pExtLoop == nullptr)
return false ;
// verifico la curva
if ( &Crv == nullptr || ! Crv.IsValid())
return false ;
// curva in locale nel riferimento intrinseco
const ICurve* pCrvLoc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_frF, GLOB_FRM))
pCrvLoc = &Crv ;
else {
pCopyCrv.Set( Crv.Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->ToLoc( m_frF) ;
pCrvLoc = Get( pCopyCrv) ;
}
// intervalli delle diverse classi
Intervals inIn, inOut, inOnP, inOnM ;
// classifico la curva con tutti i loop presenti
int nLoop = 0 ;
const ICurve* pLoop = GetMyLoop( nLoop) ;
while ( pLoop != nullptr) {
// intersezione
IntersCurveCurve ccInt( *pCrvLoc, *pLoop) ;
// classificazione
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
case CRVC_IN : inIn.Add( ccOne.dParS, ccOne.dParE) ; break ;
case CRVC_OUT : inOut.Add( ccOne.dParS, ccOne.dParE) ; break ;
case CRVC_ON_P : inOnP.Add( ccOne.dParS, ccOne.dParE) ; break ;
case CRVC_ON_M : inOnM.Add( ccOne.dParS, ccOne.dParE) ; break ;
default : return false ;
}
}
// passo al loop successivo
++ nLoop ;
pLoop = GetMyLoop( nLoop) ;
}
// sistemo gli intervalli di classificazione
// Out prevale su tutto
double dMin, dMax ;
bool bFound = inOut.GetFirst( dMin, dMax) ;
while ( bFound) {
inIn.Remove( dMin, dMax) ;
inOnP.Remove( dMin, dMax) ;
inOnM.Remove( dMin, dMax) ;
bFound = inOut.GetNext( dMin, dMax) ;
}
// OnP e OnM prevalgono su In e sono sicuramente disgiunti tra loro
bFound = inOnP.GetFirst( dMin, dMax) ;
while ( bFound) {
inIn.Remove( dMin, dMax) ;
bFound = inOnP.GetNext( dMin, dMax) ;
}
bFound = inOnM.GetFirst( dMin, dMax) ;
while ( bFound) {
inIn.Remove( dMin, dMax) ;
bFound = inOnM.GetNext( dMin, dMax) ;
}
// ricostruisco la classificazione completa e la ordino
bFound = inIn.GetFirst( dMin, dMax) ;
while ( bFound) {
ccClass.emplace_back( dMin, dMax, CRVC_IN) ;
bFound = inIn.GetNext( dMin, dMax) ;
}
bFound = inOut.GetFirst( dMin, dMax) ;
while ( bFound) {
ccClass.emplace_back( dMin, dMax, CRVC_OUT) ;
bFound = inOut.GetNext( dMin, dMax) ;
}
bFound = inOnP.GetFirst( dMin, dMax) ;
while ( bFound) {
ccClass.emplace_back( dMin, dMax, CRVC_ON_P) ;
bFound = inOnP.GetNext( dMin, dMax) ;
}
bFound = inOnM.GetFirst( dMin, dMax) ;
while ( bFound) {
ccClass.emplace_back( dMin, dMax, CRVC_ON_M) ;
bFound = inOnM.GetNext( dMin, dMax) ;
}
sort( ccClass.begin(), ccClass.end(),
[]( const CrvClass& a, const CrvClass& b) { return a.dParS < b.dParS ; }) ;
return true ;
}