42c5ffb014
- correzioni e migliorie a IntersCurveCurve.
1768 lines
56 KiB
C++
1768 lines
56 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 "CurveComposite.h"
|
|
#include "CurveLine.h"
|
|
#include "AdjustLoops.h"
|
|
#include "GeoConst.h"
|
|
#include "Voronoi.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include "/EgtDev/Include/EGkUiUnits.h"
|
|
#include "/EgtDev/Include/EGkIntervals.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
#define SAVECLASSCRV 0
|
|
#if SAVECLASSCRV
|
|
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
|
#endif
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
GEOOBJ_REGISTER( SRF_FLATRGN, NGE_S_FRG, SurfFlatRegion) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfFlatRegion::SurfFlatRegion( void)
|
|
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_pVoronoiObj( nullptr)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfFlatRegion::~SurfFlatRegion( void)
|
|
{
|
|
Clear() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::Clear( void)
|
|
{
|
|
m_nStatus = TO_VERIFY ;
|
|
m_frF.Reset() ;
|
|
|
|
// pulizia dei loop
|
|
for ( auto& pLoop : m_vpLoop)
|
|
delete pLoop ;
|
|
m_vpLoop.clear() ;
|
|
m_vExtInd.clear() ;
|
|
|
|
m_nTempProp[0] = 0 ;
|
|
m_nTempProp[1] = 0 ;
|
|
m_dTempParam[0] = 0.0 ;
|
|
m_dTempParam[1] = 0.0 ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
ResetAuxSurf() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::AddExtLoop( 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 AddExtLoop( pCrv) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::AddExtLoop( ICurve* pCrv)
|
|
{
|
|
// acquisisco la curva
|
|
PtrOwner<ICurve> pMyCrv( pCrv) ;
|
|
if ( IsNull( pMyCrv))
|
|
return false ;
|
|
// verifico sia chiusa
|
|
if ( ! pMyCrv->IsClosed())
|
|
return false ;
|
|
// verifico sia piana e imposto estrusione come normale al piano
|
|
double dArea ;
|
|
Plane3d plPlane ;
|
|
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
|
return false ;
|
|
pMyCrv->SetExtrusion( plPlane.GetVersN()) ;
|
|
pMyCrv->SetThickness( 0) ;
|
|
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
|
|
ICURVEPLIST CrvLst ;
|
|
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
|
return false ;
|
|
// aggiungo le singole curve
|
|
int nExtAdded = 0 ;
|
|
bool bOk = true ;
|
|
for ( auto& pSingCrv : CrvLst) {
|
|
bool bAdded = false ;
|
|
if ( AddSimpleExtLoop( pSingCrv, bAdded))
|
|
++ nExtAdded ;
|
|
else
|
|
bOk = false ;
|
|
|
|
}
|
|
return ( bOk && nExtAdded > 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
|
{
|
|
// default
|
|
bAdded = false ;
|
|
// acquisisco la curva
|
|
PtrOwner<ICurve> pMyCrv( pCrv) ;
|
|
if ( IsNull( pMyCrv))
|
|
return false ;
|
|
// verifico sia chiusa
|
|
if ( ! pMyCrv->IsClosed())
|
|
return false ;
|
|
// verifico sia piana
|
|
double dArea ;
|
|
Plane3d plPlane ;
|
|
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
|
return false ;
|
|
if ( dArea < SQ_EPS_SMALL)
|
|
return true ;
|
|
// se sto costruendo il primo chunk
|
|
if ( m_vExtInd.empty()) {
|
|
// assegno il riferimento intrinseco
|
|
if ( ! m_frF.Set( ORIG + plPlane.GetVersN() * plPlane.GetDist(), plPlane.GetVersN()))
|
|
return false ;
|
|
// sistemo il senso di rotazione (deve essere CCW -> area > 0)
|
|
if ( dArea < 0)
|
|
pMyCrv->Invert() ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// verifico che il piano della curva coincida con quello XY intrinseco
|
|
plPlane.ToLoc( m_frF) ;
|
|
if ( ! plPlane.GetVersN().IsZEpsilon( 2 * EPS_ZERO) || abs( plPlane.GetDist()) > EPS_SMALL)
|
|
return false ;
|
|
// sistemo il senso di rotazione (deve essere CCW -> area > 0)
|
|
if ( ( plPlane.GetVersN().z > 0 && dArea < 0) ||
|
|
( plPlane.GetVersN().z < 0 && dArea > 0))
|
|
pMyCrv->Invert() ;
|
|
}
|
|
// porto la curva nel riferimento intrinseco
|
|
if ( ! pMyCrv->ToLoc( m_frF))
|
|
return false ;
|
|
Vector3d vtExtr ;
|
|
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
|
|
pMyCrv->SetExtrusion( Z_AX) ;
|
|
// verifico non abbia auto-intersezioni che si attraversano o si sovrappongano
|
|
SelfIntersCurve sInt( *pMyCrv) ;
|
|
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
|
return false ;
|
|
// verifico che sia esterna alle curve esterne degli altri chunk
|
|
bool bOk = true ;
|
|
CRVCVECTOR ccClass ;
|
|
for ( auto i : m_vExtInd) {
|
|
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
|
|
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
|
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
|
|
ccClass.empty() || ccClass[0].nClass != CRVC_OUT) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
}
|
|
// oppure esterna ad un loop interno degli altri chunk
|
|
for ( int i = 0 ; i < int( m_vpLoop.size()) ; ++ i) {
|
|
// se loop esterno, salto
|
|
if ( binary_search( m_vExtInd.begin(), m_vExtInd.end(), i))
|
|
continue ;
|
|
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
|
|
if ( ccInt.GetCrossOrOverlapIntersCount() == 0 &&
|
|
ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) &&
|
|
! ccClass.empty() && ccClass[0].nClass == CRVC_OUT) {
|
|
bOk = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( ! bOk)
|
|
return false ;
|
|
// assegno la curva come loop esterno
|
|
if ( MyAddExtLoop( pMyCrv))
|
|
Release( pMyCrv) ;
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
bAdded = true ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
|
|
{
|
|
try {
|
|
m_vpLoop.push_back( pCrv) ;
|
|
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
|
m_nStatus = OK ;
|
|
}
|
|
catch (...) {
|
|
return false ;
|
|
}
|
|
|
|
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 sia chiusa
|
|
if ( ! pMyCrv->IsClosed())
|
|
return false ;
|
|
// verifico sia piana e imposto estrusione come normale al piano
|
|
double dArea ;
|
|
Plane3d plPlane ;
|
|
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
|
return false ;
|
|
pMyCrv->SetExtrusion( plPlane.GetVersN()) ;
|
|
pMyCrv->SetThickness( 0) ;
|
|
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
|
|
ICURVEPLIST CrvLst ;
|
|
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
|
return false ;
|
|
// aggiungo le singole curve
|
|
bool bOk = true ;
|
|
for ( auto& pSingCrv : CrvLst) {
|
|
if ( ! AddSimpleIntLoop( pSingCrv))
|
|
bOk = false ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
|
{
|
|
// acquisisco la curva
|
|
PtrOwner<ICurve> pMyCrv( pCrv) ;
|
|
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
|
|
return false ;
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// verifico sia chiusa
|
|
if ( ! pMyCrv->IsClosed())
|
|
return false ;
|
|
// porto la curva nel riferimento intrinseco
|
|
if ( ! pMyCrv->ToLoc( m_frF))
|
|
return false ;
|
|
Vector3d vtExtr ;
|
|
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
|
|
pMyCrv->SetExtrusion( Z_AX) ;
|
|
// verifico sia piana e il piano coincida con quello XY intrinseco
|
|
double dArea ;
|
|
Plane3d plPlane ;
|
|
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
|
return false ;
|
|
if ( ! plPlane.GetVersN().IsZEpsilon( 2 * EPS_ZERO) || abs( plPlane.GetDist()) > EPS_SMALL)
|
|
return false ;
|
|
// sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0)
|
|
if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
|
|
pMyCrv->Invert() ;
|
|
// verifico non abbia auto-intersezioni
|
|
SelfIntersCurve sInt( *pMyCrv) ;
|
|
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
|
return false ;
|
|
// ricerca del chunk in cui andrebbe inserito
|
|
int nChunk = -1 ;
|
|
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
|
|
// verifica rispetto al loop esterno
|
|
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[m_vExtInd[i]]) ;
|
|
CRVCVECTOR ccClass ;
|
|
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
|
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
|
|
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
|
continue ;
|
|
// verifica rispetto ai loop interni
|
|
bool bOk = true ;
|
|
int nLoopCnt = GetLoopCount( i) ;
|
|
for ( int j = 0 ; j < nLoopCnt ; ++ j) {
|
|
int k = m_vExtInd[i] + j ;
|
|
IntersCurveCurve ccInt2( *pMyCrv, *m_vpLoop[k]) ;
|
|
CRVCVECTOR ccClass2 ;
|
|
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
|
! ccInt2.GetCurveClassification( 0, EPS_SMALL, ccClass2) ||
|
|
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( bOk) {
|
|
nChunk = i ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( nChunk == -1)
|
|
return false ;
|
|
// aggiungo la curva all'elenco dei loop
|
|
if ( MyAddIntLoop( pMyCrv, nChunk))
|
|
Release( pMyCrv) ;
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
|
|
{
|
|
try {
|
|
// se da aggiungere all'ultimo chunk
|
|
if ( nChunk == -1)
|
|
m_vpLoop.push_back( pCrv) ;
|
|
// altrimenti aggiungo al chunck indicato
|
|
else {
|
|
int nLoopCnt = GetLoopCount( nChunk) ;
|
|
if ( nLoopCnt == 0)
|
|
return false ;
|
|
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
|
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
|
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
|
++ m_vExtInd[i] ;
|
|
}
|
|
}
|
|
catch (...) {
|
|
return false ;
|
|
}
|
|
|
|
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 = GetBasicSurfFlatRegion( 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 ;
|
|
for ( auto& pLoop : sfrSrc.m_vpLoop) {
|
|
ICurve* pCrv = pLoop->Clone() ;
|
|
if ( pCrv == nullptr)
|
|
return false ;
|
|
m_vpLoop.push_back( pCrv) ;
|
|
}
|
|
m_vExtInd = sfrSrc.m_vExtInd ;
|
|
m_nTempProp[0] = sfrSrc.m_nTempProp[0] ;
|
|
m_nTempProp[1] = sfrSrc.m_nTempProp[1] ;
|
|
m_dTempParam[0] = sfrSrc.m_dTempParam[0] ;
|
|
m_dTempParam[1] = sfrSrc.m_dTempParam[1] ;
|
|
m_nStatus = sfrSrc.m_nStatus ;
|
|
return ( m_nStatus == OK && ! m_vpLoop.empty()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
GeoObjType
|
|
SurfFlatRegion::GetType( void) const
|
|
{
|
|
return static_cast<GeoObjType>( GEOOBJ_GETTYPE( SurfFlatRegion)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
SurfFlatRegion::GetTitle( void) const
|
|
{
|
|
static const string sTitle = "SurfFr" ;
|
|
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 ;
|
|
// ciclo sui chunk (parti connesse)
|
|
int nChunkCount = GetChunkCount() ;
|
|
sOut += string( "Chunks =") + ToString( nChunkCount) + szNewLine ;
|
|
for ( int i = 0 ; i < nChunkCount ; ++ i) {
|
|
int nLoopCount = GetLoopCount( i) ;
|
|
// ciclo sui loop del chunk
|
|
for ( int j = 0 ; j < nLoopCount ; ++ j) {
|
|
int k = GetIndFromChunkLoop( i, j) ;
|
|
// loop esterno
|
|
if ( j == 0) {
|
|
sOut += "Chunk # " + ToString( i) + szNewLine ;
|
|
sOut += string( "External Loop : ") + szNewLine ;
|
|
m_vpLoop[k]->Dump( sOut, bMM, szNewLine) ;
|
|
sOut += "Internal Loops =" + ToString( GetLoopCount( i) - 1) + szNewLine ;
|
|
}
|
|
// loop interno
|
|
else {
|
|
sOut += "## " + ToString( j) + szNewLine ;
|
|
m_vpLoop[k]->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( int( m_vpLoop.size()), nullptr, true))
|
|
return false ;
|
|
// ciclo sui loop
|
|
int i = 0 ;
|
|
for ( auto& pLoop : m_vpLoop) {
|
|
// recupero il gestore di lettura/scrittura della curva
|
|
const IGeoObjRW* pLoopRW = dynamic_cast<const IGeoObjRW*>( pLoop) ;
|
|
if ( pLoopRW == nullptr)
|
|
return false ;
|
|
// emetto il tipo della curva
|
|
if ( ! ngeOut.WriteKey( pLoopRW->GetNgeId()))
|
|
return false ;
|
|
// assegno ed emetto il nome della curva, seguito da chunk e loop
|
|
string sCrvName = "##" + ToString( i) ;
|
|
if ( ! ngeOut.WriteString( sCrvName, ";"))
|
|
return false ;
|
|
int nChunk, nLoop ;
|
|
if ( ! GetChunkLoopFromInd( i, nChunk, nLoop))
|
|
return false ;
|
|
if ( ! ngeOut.WriteInt( nChunk, ",") ||
|
|
! ngeOut.WriteInt( nLoop, ";", true))
|
|
return false ;
|
|
// salvo la curva
|
|
if ( ! pLoopRW->Save( ngeOut))
|
|
return false ;
|
|
// passo alla successiva
|
|
++ 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, chunk e loop
|
|
string sName ;
|
|
int j ;
|
|
bool bOk = ngeIn.ReadString( sName, ";") &&
|
|
FromString( sName.substr( 2), j) && i == j ;
|
|
int nChunk = 0, nLoop = 0 ;
|
|
bOk = ngeIn.ReadInt( nChunk, ",") &&
|
|
ngeIn.ReadInt( nLoop, ";", true) ;
|
|
// 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) {
|
|
m_vpLoop.push_back( pCrv) ;
|
|
if ( nLoop == 0) {
|
|
m_vExtInd.push_back( i) ;
|
|
bOk = ( nChunk + 1 == int( m_vExtInd.size())) ;
|
|
}
|
|
}
|
|
// 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_vpLoop.empty())
|
|
return false ;
|
|
// reset del bbox
|
|
b3Loc.Reset() ;
|
|
// è il bounding box dei loop esterni
|
|
for ( auto i : m_vExtInd) {
|
|
BBox3d b3Tmp ;
|
|
if ( m_vpLoop[i]->GetBBox( m_frF, b3Tmp, nFlag))
|
|
b3Loc.Add( b3Tmp) ;
|
|
}
|
|
return ( ! b3Loc.IsEmpty()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// frame composito
|
|
Frame3d frCompo = m_frF * frRef ;
|
|
// reset del bbox
|
|
b3Ref.Reset() ;
|
|
// è il bounding box dei loop esterni
|
|
for ( auto i : m_vExtInd) {
|
|
BBox3d b3Tmp ;
|
|
if ( m_vpLoop[i]->GetBBox( frCompo, b3Tmp, nFlag))
|
|
b3Ref.Add( b3Tmp) ;
|
|
}
|
|
return ( ! b3Ref.IsEmpty()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::Translate( const Vector3d& vtMove)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// traslo Voronoi
|
|
if ( m_pVoronoiObj != nullptr)
|
|
m_pVoronoiObj->Translate( vtMove) ;
|
|
// 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 ;
|
|
// verifico validità dell'asse di rotazione
|
|
if ( vtAx.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// ruoto Voronoi
|
|
if ( m_pVoronoiObj != nullptr)
|
|
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
|
|
// 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_vpLoop.empty())
|
|
return false ;
|
|
// verifico non sia nulla
|
|
if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
|
|
// se scalatura non uniforme, sostituisco eventuali archi con curve di Bezier
|
|
if ( abs( dCoeffX - dCoeffY) > EPS_SMALL || abs( 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) ;
|
|
for ( auto& pLoop : m_vpLoop)
|
|
pLoop->ToGlob( frTrasf) ;
|
|
|
|
// porto il riferimento di scalatura nel nuovo riferimento del gruppo
|
|
Frame3d frRefLoc = frRef ;
|
|
frRefLoc.ToLoc( m_frF) ;
|
|
|
|
// determino se contiene anche un mirror (numero dispari di coefficienti negativi)
|
|
bool bMirror = ( dCoeffX < 0) ;
|
|
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
|
|
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
|
|
|
|
// ciclo sui loop
|
|
bool bOk = true ;
|
|
for ( auto& pLoop : m_vpLoop) {
|
|
if ( ! pLoop->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ))
|
|
bOk = false ;
|
|
if ( bMirror) {
|
|
if ( ! pLoop->Invert())
|
|
bOk = false ;
|
|
}
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// verifico validità del piano di specchiatura
|
|
if ( vtNorm.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
|
|
// 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) ;
|
|
for ( auto& pLoop : m_vpLoop)
|
|
pLoop->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 = true ;
|
|
for ( auto& pLoop : m_vpLoop) {
|
|
if ( ! pLoop->Mirror( ptOnLoc, vtNormLoc) || ! pLoop->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_vpLoop.empty())
|
|
return false ;
|
|
// verifico validità dei parametri
|
|
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
|
|
// 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) ;
|
|
for ( auto& pLoop : m_vpLoop)
|
|
pLoop->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 = true ;
|
|
for ( auto& pLoop : m_vpLoop) {
|
|
if ( ! pLoop->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff))
|
|
bOk = false ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::ConvertArcsToBezierCurves( void)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// ciclo sui loop
|
|
for ( auto& pLoop : m_vpLoop) {
|
|
if ( pLoop->GetType() == CRV_ARC) {
|
|
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc(pLoop)) ;
|
|
if ( pCrvNew == nullptr)
|
|
return false ;
|
|
delete pLoop ;
|
|
pLoop = pCrvNew ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::ToGlob( const Frame3d& frRef)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// se frame identità, non devo fare alcunché
|
|
if ( IsGlobFrame( frRef))
|
|
return true ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo Voronoi
|
|
if ( m_pVoronoiObj != nullptr)
|
|
m_pVoronoiObj->ToGlob( frRef) ;
|
|
|
|
// trasformo il riferimento
|
|
return m_frF.ToGlob( frRef) ; ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::ToLoc( const Frame3d& frRef)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// se frame identità, non devo fare alcunché
|
|
if ( IsGlobFrame( frRef))
|
|
return true ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo Voronoi
|
|
if ( m_pVoronoiObj != nullptr)
|
|
m_pVoronoiObj->ToLoc( frRef) ;
|
|
|
|
// 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 ;
|
|
// verifico validità dei frame
|
|
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// se i due riferimenti coincidono, non devo fare alcunché
|
|
if ( AreSameFrame( frOri, frDest))
|
|
return true ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
ResetAuxSurf() ;
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo Voronoi
|
|
if ( m_pVoronoiObj != nullptr)
|
|
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
|
|
|
|
// trasformo il riferimento
|
|
return m_frF.LocToLoc( frOri, frDest) ; ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetArea( double& dArea) const
|
|
{
|
|
// inizio con area nulla
|
|
dArea = 0 ;
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// sommo l'area di tutti i loop (gli interni hanno area negativa)
|
|
bool bOk = true ;
|
|
for ( const auto& pLoop : m_vpLoop) {
|
|
double dTemp ;
|
|
if ( pLoop->GetAreaXY( dTemp))
|
|
dArea += dTemp ;
|
|
else
|
|
bOk = false ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetGrossArea( double& dArea) const
|
|
{
|
|
// inizio con area nulla
|
|
dArea = 0 ;
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// sommo l'area di tutti e soli i loop esterni (con area positiva)
|
|
bool bOk = true ;
|
|
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
|
double dTemp ;
|
|
const ICurve* pCrv = GetMyLoop( i, 0) ;
|
|
if ( pCrv != nullptr && pCrv->GetAreaXY( dTemp))
|
|
dArea += abs( dTemp) ;
|
|
else
|
|
bOk = false ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetCentroid( Point3d& ptCen) const
|
|
{
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// determino il centroide dei soli loop esterni
|
|
double dArea = 0 ;
|
|
ptCen = ORIG ;
|
|
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
|
Point3d ptC ;
|
|
double dA ;
|
|
const ICurve* pCrv = GetMyLoop( i, 0) ;
|
|
if ( pCrv == nullptr || ! pCrv->GetCentroid( ptC) || ! pCrv->GetAreaXY( dA))
|
|
return false ;
|
|
ptCen += ptC * abs( dA) ;
|
|
dArea += abs( dA) ;
|
|
}
|
|
// verifico di aver trovato qualcosa
|
|
if ( dArea < SQ_EPS_SMALL)
|
|
return false ;
|
|
// medio il centro
|
|
ptCen /= dArea ;
|
|
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
|
|
ptCen.ToGlob( m_frF) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfFlatRegion::GetChunkCount( void) const
|
|
{
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return 0 ;
|
|
return int( m_vExtInd.size()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
|
|
{
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// determino il centroide del solo loop esterno del chunk
|
|
const ICurve* pCrv = GetMyLoop( nChunk, 0) ;
|
|
if ( pCrv == nullptr || ! pCrv->GetCentroid( ptCen))
|
|
return false ;
|
|
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
|
|
ptCen.ToGlob( m_frF) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetChunkArea( int nChunk, double& dArea) const
|
|
{
|
|
// default, area nulla
|
|
dArea = 0 ;
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// il chunk deve esistere
|
|
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
|
return false ;
|
|
// calcolo l'area
|
|
bool bOk = true ;
|
|
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
|
|
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
|
|
double dLoopArea ;
|
|
if ( pLoop != nullptr && pLoop->GetAreaXY( dLoopArea))
|
|
dArea += dLoopArea ;
|
|
else
|
|
bOk = false ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetChunkPerimeter( int nChunk, double& dLen) const
|
|
{
|
|
// default, perimetro nullo
|
|
dLen = 0 ;
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// il chunk deve esistere
|
|
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
|
return false ;
|
|
// calcolo il perimetro
|
|
bool bOk = true ;
|
|
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
|
|
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
|
|
double dLoopLen ;
|
|
if ( pLoop != nullptr && pLoop->GetLength( dLoopLen))
|
|
dLen += dLoopLen ;
|
|
else
|
|
bOk = false ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfFlatRegion::GetLoopCount( int nChunk) const
|
|
{
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return 0 ;
|
|
// non deve superare l'indice massimo ( Count - 1)
|
|
int nChunkMax = int( m_vExtInd.size()) - 1 ;
|
|
if ( nChunk < 0 || nChunk > nChunkMax)
|
|
return 0 ;
|
|
// se non è l'ultimo Chunk
|
|
if ( nChunk < nChunkMax)
|
|
return ( m_vExtInd[nChunk+1] - m_vExtInd[nChunk]) ;
|
|
// altrimenti
|
|
else
|
|
return ( int( m_vpLoop.size()) - m_vExtInd[nChunk]) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfFlatRegion::GetIndFromChunkLoop( int nChunk, int nLoop) const
|
|
{
|
|
// recupero il numero di loop nel chunk
|
|
int nLoopCount = GetLoopCount( nChunk) ;
|
|
if ( nLoopCount <= 0)
|
|
return - 1 ;
|
|
// verifico che il loop esista
|
|
if ( nLoop < 0 || nLoop >= nLoopCount)
|
|
return - 1 ;
|
|
// ritorno il suo indice
|
|
return ( m_vExtInd[nChunk] + nLoop) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const
|
|
{
|
|
// valori non validi
|
|
nChunk = - 1 ;
|
|
nLoop = - 1 ;
|
|
// verifico validità di nInd
|
|
if ( nInd < 0 || nInd >= int( m_vpLoop.size()))
|
|
return false ;
|
|
// verifica esistenza array di chunks
|
|
if ( m_vExtInd.empty())
|
|
return false ;
|
|
// ricerca del chunk e del loop
|
|
nChunk = 0 ;
|
|
while ( ( nChunk + 1) < int( m_vExtInd.size())) {
|
|
if ( nInd < m_vExtInd[nChunk+1])
|
|
break ;
|
|
++ nChunk ;
|
|
}
|
|
nLoop = nInd - m_vExtInd[nChunk] ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
SurfFlatRegion::GetMyLoop( int nInd) const
|
|
{
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return nullptr ;
|
|
// verifico che l'indice sia nei limiti
|
|
if ( nInd < 0 || nInd >= int( m_vpLoop.size()))
|
|
return nullptr ;
|
|
else
|
|
return m_vpLoop[nInd] ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
SurfFlatRegion::GetMyLoop( int nChunk, int nLoop) const
|
|
{
|
|
return GetMyLoop( GetIndFromChunkLoop( nChunk, nLoop)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
SurfFlatRegion::GetLoop( int nChunk, int nLoop) const
|
|
{
|
|
// recupero il loop nel riferimento intrinseco
|
|
const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pMyCrv == nullptr)
|
|
return nullptr ;
|
|
// ne faccio una copia
|
|
ICurve* pCrv = pMyCrv->Clone() ;
|
|
if ( pCrv == nullptr)
|
|
return nullptr ;
|
|
// assegno la normale alla regione come estrusione
|
|
pCrv->SetExtrusion( Z_AX) ;
|
|
// la porto nel riferimento in cui è inserito l'oggetto
|
|
pCrv->ToGlob( m_frF) ;
|
|
return pCrv ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfFlatRegion::GetLoopCurveCount( int nChunk, int nLoop) const
|
|
{
|
|
// recupero il loop nel riferimento intrinseco
|
|
const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pMyCrv == nullptr)
|
|
return 0 ;
|
|
// restituisco il numero di curve di cui è composto
|
|
const ICurveComposite* pMyCompo = GetCurveComposite( pMyCrv) ;
|
|
return ( pMyCompo == nullptr ? 1 : pMyCompo->GetCurveCount()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const
|
|
{
|
|
// recupero il loop nel riferimento intrinseco
|
|
const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pMyCrv == nullptr)
|
|
return false ;
|
|
// ne creo una approssimazione
|
|
if ( ! pMyCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, PL))
|
|
return false ;
|
|
// la porto nel riferimento in cui è inserito l'oggetto
|
|
PL.ToGlob( m_frF) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfTriMesh*
|
|
SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return nullptr ;
|
|
// la creo
|
|
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pSTM))
|
|
return nullptr ;
|
|
// per ogni chunk (componente connesso)
|
|
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
|
// calcolo le polilinee che approssimano i loop
|
|
POLYLINEVECTOR vPL ;
|
|
vPL.reserve( GetLoopCount( i)) ;
|
|
int j = 0 ;
|
|
ICurve* pLoop = GetMyLoop( i, j) ;
|
|
while ( pLoop != nullptr) {
|
|
// approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
|
|
vPL.emplace_back( PolyLine()) ;
|
|
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL.back()))
|
|
return nullptr ;
|
|
double dLoopArea ;
|
|
if ( ! vPL.back().GetAreaXY( dLoopArea) || abs( dLoopArea) <= 25 * SQ_EPS_SMALL)
|
|
vPL.pop_back() ;
|
|
pLoop = GetMyLoop( i, ++j) ;
|
|
}
|
|
// se chunk abbastanza grande, creo la superficie trimesh relativa
|
|
double dArea ;
|
|
if ( ! vPL.empty() && vPL[0].GetAreaXY( dArea) && dArea > 25 * SQ_EPS_SMALL) {
|
|
// creo, setto la superficie trimesh ed elimino punti ripetuti
|
|
PtrOwner<SurfTriMesh> pChSTM( CreateBasicSurfTriMesh()) ;
|
|
INTMATRIX vnPLIndMat ;
|
|
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL, vnPLIndMat) || ! pChSTM->DoCompacting())
|
|
return nullptr ;
|
|
// porto la trimesh in globale al riferimento intrinseco
|
|
pChSTM->ToGlob( m_frF) ;
|
|
// inserisco questa trimesh in quella complessiva
|
|
pSTM->DoSewing( *pChSTM) ;
|
|
}
|
|
}
|
|
// se vuota
|
|
if ( pSTM->IsEmpty())
|
|
pSTM->AdjustTopology() ;
|
|
// la restituisco
|
|
return Release( pSTM) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const SurfTriMesh*
|
|
SurfFlatRegion::GetAuxSurf( void) const
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return nullptr ;
|
|
// se già calcolata, la restituisco
|
|
if ( m_pSTM != nullptr)
|
|
return m_pSTM ;
|
|
// la creo e la salvo
|
|
m_pSTM = CalcAuxSurf( LIN_TOL_FINE, ANG_TOL_STD_DEG) ;
|
|
return m_pSTM ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
SurfFlatRegion::ResetAuxSurf( void) const
|
|
{
|
|
if ( m_pSTM != nullptr)
|
|
delete( m_pSTM) ;
|
|
m_pSTM = nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfFlatRegion*
|
|
SurfFlatRegion::CloneChunk( int nChunk) const
|
|
{
|
|
// verifico esistenza del chunk (implicitamente anche lo stato)
|
|
int nLoop = GetLoopCount( nChunk) ;
|
|
if ( nLoop == 0)
|
|
return nullptr ;
|
|
// alloco la nuova regione
|
|
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
|
|
if ( IsNull( pSfr))
|
|
return nullptr ;
|
|
// copio il riferimento intrinseco
|
|
pSfr->m_frF = m_frF ;
|
|
// copio i loop del chunk indicato
|
|
for ( int i = 0 ; i < nLoop ; ++i) {
|
|
ICurve* pCrv = GetMyLoop( nChunk, i)->Clone() ;
|
|
if ( pCrv == nullptr)
|
|
return nullptr ;
|
|
pSfr->m_vpLoop.push_back( pCrv) ;
|
|
}
|
|
// sistemo indice dell'unico loop esterno
|
|
pSfr->m_vExtInd.push_back( 0) ;
|
|
pSfr->m_nStatus = OK ;
|
|
return Release( pSfr) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::EraseChunk(int nChunk)
|
|
{
|
|
// la regione deve essere validata
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// il chunk deve esistere
|
|
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
|
return false ;
|
|
// se un solo chunk, resetto la regione
|
|
if ( GetChunkCount() == 1) {
|
|
Clear() ;
|
|
return true ;
|
|
}
|
|
// se ultimo chunk
|
|
if ( nChunk == m_vExtInd.size() - 1) {
|
|
// elimino i loop
|
|
for ( int i = m_vExtInd[nChunk] ; i < int( m_vpLoop.size()) ; ++ i) {
|
|
delete m_vpLoop[i] ;
|
|
m_vpLoop[i] = nullptr ;
|
|
}
|
|
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.end()) ;
|
|
// elimino indice di loop esterno
|
|
m_vExtInd.pop_back() ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// numero di loop da eliminare
|
|
int nLoopCnt = m_vExtInd[nChunk+1] - m_vExtInd[nChunk] ;
|
|
// elimino i loop
|
|
for ( int i = m_vExtInd[nChunk] ; i < m_vExtInd[nChunk+1] ; ++ i) {
|
|
delete m_vpLoop[i] ;
|
|
m_vpLoop[i] = nullptr ;
|
|
}
|
|
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.begin() + m_vExtInd[nChunk+1]) ;
|
|
// elimino indice di loop esterno
|
|
m_vExtInd.erase( m_vExtInd.begin() + nChunk) ;
|
|
// aggiorno indice inizio chunk successivi
|
|
for ( int i = nChunk ; i < int( m_vExtInd.size()) ; ++i)
|
|
m_vExtInd[i] -= nLoopCnt ;
|
|
}
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
ResetAuxSurf() ;
|
|
// imposto ricalcolo Voronoi
|
|
ResetVoronoiObject() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
|
|
{
|
|
// la curva deve già essere nel riferimento intrinseco della regione
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
return false ;
|
|
// verifico la curva
|
|
if ( &Crv == nullptr || ! Crv.IsValid())
|
|
return false ;
|
|
// dominio della curva
|
|
double dStart, dEnd ;
|
|
if ( ! Crv.GetDomain( dStart, dEnd))
|
|
return false ;
|
|
|
|
// intervalli totali delle diverse classi
|
|
Intervals inTIn( EPS_PARAM), inTOut( EPS_PARAM), inTOnP( EPS_PARAM), inTOnM( EPS_PARAM) ;
|
|
inTOut.Set( dStart, dEnd) ; // inizializzo come tutta la linea per poi poter rimuovere parti
|
|
// ciclo sui chunk
|
|
for ( int nChunk = 0 ; nChunk < GetChunkCount() ; ++ nChunk) {
|
|
// intervalli di Chunk delle diverse classi
|
|
Intervals inCIn( EPS_PARAM), inCOut( EPS_PARAM), inCOnP( EPS_PARAM), inCOnM( EPS_PARAM) ;
|
|
inCIn.Set( dStart, dEnd) ; // inizializzo come tutta la linea per poi poter rimuovere parti
|
|
// classifico la curva con tutti i loop presenti nel chunk
|
|
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
|
|
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
|
// intersezione
|
|
|
|
#if SAVECLASSCRV
|
|
//debug
|
|
vector<IGeoObj*> vGeo ;
|
|
vGeo.push_back( Crv.Clone()) ;
|
|
vGeo.push_back( pLoop->Clone()) ;
|
|
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\crv_and_loop.nge") ;
|
|
#endif
|
|
|
|
IntersCurveCurve ccInt( Crv, *pLoop) ;
|
|
// classificazione
|
|
CRVCVECTOR ccPart ;
|
|
if ( ! ccInt.GetCurveClassification( 0, dLenMin, ccPart))
|
|
return false ;
|
|
for ( auto& ccOne : ccPart) {
|
|
switch ( ccOne.nClass) {
|
|
case CRVC_IN :
|
|
// IN è Remove degli altri
|
|
break ;
|
|
case CRVC_OUT :
|
|
// intervallo standard
|
|
if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) {
|
|
inCOut.Add( ccOne.dParS, ccOne.dParE) ;
|
|
inCIn.Subtract( ccOne.dParS, ccOne.dParE) ;
|
|
}
|
|
// intervallo che attraversa punto di chiusura della curva
|
|
else {
|
|
inCOut.Add( ccOne.dParS, dEnd) ;
|
|
inCOut.Add( dStart, ccOne.dParE) ;
|
|
inCIn.Subtract( ccOne.dParS, dEnd) ;
|
|
inCIn.Subtract( dStart, ccOne.dParE) ;
|
|
}
|
|
break ;
|
|
case CRVC_ON_P :
|
|
// intervallo standard
|
|
if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) {
|
|
inCOnP.Add( ccOne.dParS, ccOne.dParE) ;
|
|
inCIn.Subtract( ccOne.dParS, ccOne.dParE) ;
|
|
}
|
|
// intervallo che attraversa punto di chiusura della curva
|
|
else {
|
|
inCOnP.Add( ccOne.dParS, dEnd) ;
|
|
inCOnP.Add( dStart, ccOne.dParE) ;
|
|
inCIn.Subtract( ccOne.dParS, dEnd) ;
|
|
inCIn.Subtract( dStart, ccOne.dParE) ;
|
|
}
|
|
break ;
|
|
case CRVC_ON_M :
|
|
// intervallo standard
|
|
if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) {
|
|
inCOnM.Add( ccOne.dParS, ccOne.dParE) ;
|
|
inCIn.Subtract( ccOne.dParS, ccOne.dParE) ;
|
|
}
|
|
// intervallo che attraversa punto di chiusura della curva
|
|
else {
|
|
inCOnM.Add( ccOne.dParS, dEnd) ;
|
|
inCOnM.Add( dStart, ccOne.dParE) ;
|
|
inCIn.Subtract( ccOne.dParS, dEnd) ;
|
|
inCIn.Subtract( dStart, ccOne.dParE) ;
|
|
}
|
|
break ;
|
|
default : return false ;
|
|
}
|
|
}
|
|
}
|
|
// aggiorno gli intervalli di classificazione totali
|
|
// In, OnP e OnM vengono aggiornati per somma
|
|
inTIn.Add( inCIn) ;
|
|
inTOnP.Add( inCOnP) ;
|
|
inTOnM.Add( inCOnM) ;
|
|
// Out viene ricavato per differenza degli altri
|
|
inTOut.Subtract( inCIn) ;
|
|
inTOut.Subtract( inCOnP) ;
|
|
inTOut.Subtract( inCOnM) ;
|
|
}
|
|
|
|
// ricostruisco la classificazione completa e la ordino
|
|
double dMin, dMax ;
|
|
bool bFound = inTIn.GetFirst( dMin, dMax) ;
|
|
while ( bFound) {
|
|
ccClass.emplace_back( dMin, dMax, CRVC_IN) ;
|
|
bFound = inTIn.GetNext( dMin, dMax) ;
|
|
}
|
|
bFound = inTOut.GetFirst( dMin, dMax) ;
|
|
while ( bFound) {
|
|
ccClass.emplace_back( dMin, dMax, CRVC_OUT) ;
|
|
bFound = inTOut.GetNext( dMin, dMax) ;
|
|
}
|
|
bFound = inTOnP.GetFirst( dMin, dMax) ;
|
|
while ( bFound) {
|
|
ccClass.emplace_back( dMin, dMax, CRVC_ON_P) ;
|
|
bFound = inTOnP.GetNext( dMin, dMax) ;
|
|
}
|
|
bFound = inTOnM.GetFirst( dMin, dMax) ;
|
|
while ( bFound) {
|
|
ccClass.emplace_back( dMin, dMax, CRVC_ON_M) ;
|
|
bFound = inTOnM.GetNext( dMin, dMax) ;
|
|
}
|
|
sort( ccClass.begin(), ccClass.end(),
|
|
[]( const CrvClass& a, const CrvClass& b) { return ( a.dParS < b.dParS) ; }) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK || m_vpLoop.empty())
|
|
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 = pCopyCrv ;
|
|
}
|
|
// esecuzione classificazione nel riferimento intrinseco
|
|
return MyGetCurveClassification( *pCrvLoc, dLenMin, ccClass) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const
|
|
{
|
|
// verifico lo stato e il numero di chunk
|
|
if ( m_nStatus != OK || m_vpLoop.empty() || nChunk >= GetChunkCount())
|
|
return REGC_NULL ;
|
|
// recupero rappresentazione base dell'altra regione
|
|
const SurfFlatRegion& Reg2 = *GetBasicSurfFlatRegion( &Other) ;
|
|
// verifico lo stato e il numero di chunk dell'altra regione
|
|
if ( &Reg2 == nullptr || Reg2.m_nStatus != OK || Reg2.m_vpLoop.empty() || nOthChunk >= Reg2.GetChunkCount())
|
|
return REGC_NULL ;
|
|
|
|
// verifico che le due regioni giacciano in piani paralleli
|
|
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
|
|
return REGC_NULL ;
|
|
|
|
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
|
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
|
|
|
|
// curva esterna del chunk della seconda regione in locale nel riferimento intrinseco della prima
|
|
const ICurve* pCrv2Loc = nullptr ;
|
|
PtrOwner<ICurve> pCopyCrv ;
|
|
if ( AreSameFrame( m_frF, Reg2.m_frF))
|
|
pCrv2Loc = Reg2.GetMyLoop( nOthChunk, 0) ;
|
|
else {
|
|
pCopyCrv.Set( Reg2.GetMyLoop( nOthChunk, 0)->Clone()) ;
|
|
if ( IsNull( pCopyCrv))
|
|
return REGC_NULL ;
|
|
pCopyCrv->LocToLoc( Reg2.m_frF, m_frF) ;
|
|
pCrv2Loc = pCopyCrv ;
|
|
}
|
|
|
|
// se i box delle due curve sono esterni, i chunk sono esterni
|
|
BBox3d b3Crv1, b3Crv2 ;
|
|
pCrv1Loc->GetLocalBBox( b3Crv1) ;
|
|
pCrv2Loc->GetLocalBBox( b3Crv2) ;
|
|
if ( ! b3Crv1.OverlapsXY( b3Crv2))
|
|
return REGC_OUT ;
|
|
|
|
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
|
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
|
|
int nClass = ccInt.GetRegionCurveClassification() ;
|
|
switch ( nClass){
|
|
default : // CCREGC_NULL
|
|
return REGC_NULL ;
|
|
case CCREGC_IN1 :
|
|
return REGC_IN1 ;
|
|
case CCREGC_IN2 :
|
|
return REGC_IN2 ;
|
|
case CCREGC_SAME :
|
|
return REGC_SAME ;
|
|
case CCREGC_OUT :
|
|
return REGC_OUT ;
|
|
case CCREGC_INTERS :
|
|
return REGC_INTERS ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::CalcVoronoiObject() const
|
|
{
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// creo oggetto vroni con la superficie
|
|
m_pVoronoiObj = new( std::nothrow) Voronoi( this, false) ;
|
|
if ( m_pVoronoiObj == nullptr)
|
|
return false ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
SurfFlatRegion::ResetVoronoiObject() const
|
|
{
|
|
if ( m_pVoronoiObj != nullptr)
|
|
delete m_pVoronoiObj ;
|
|
m_pVoronoiObj = nullptr ;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) const
|
|
{
|
|
// verifico se è stato calcolato
|
|
if ( m_pVoronoiObj == nullptr)
|
|
if ( ! CalcVoronoiObject())
|
|
return false ;
|
|
|
|
return m_pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const
|
|
{
|
|
// verifico se è stato calcolato
|
|
if ( m_pVoronoiObj == nullptr)
|
|
if ( ! CalcVoronoiObject())
|
|
return false ;
|
|
|
|
return m_pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetChunkMaxOffset( int nChunk, double& dOffs) const
|
|
{
|
|
// verifico se è stato calcolato Voronoi
|
|
if ( m_pVoronoiObj == nullptr)
|
|
if ( ! CalcVoronoiObject())
|
|
return false ;
|
|
|
|
// il massimo offset per il chunk è il massimo offset del suo loop esterno
|
|
// ( il diagramma di Voronoi tiene già conto della limitazione con i loop interni)
|
|
int nInd = GetIndFromChunkLoop( nChunk, 0) ;
|
|
return m_pVoronoiObj->CalcLimitOffset( nInd, true, dOffs) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetMaxOffset( double& dOffs) const
|
|
{
|
|
int nChunks = GetChunkCount() ;
|
|
if ( nChunks == 0)
|
|
return false ;
|
|
|
|
// calcolo il massimo fra gli offset limite di tutti i suoi chunks
|
|
if ( ! GetChunkMaxOffset( 0, dOffs))
|
|
return false ;
|
|
for ( int i = 1 ; i < nChunks ; i++) {
|
|
double dCurrOffs ;
|
|
if ( ! GetChunkMaxOffset( i, dCurrOffs))
|
|
return false ;
|
|
if ( dCurrOffs > dOffs)
|
|
dOffs = dCurrOffs ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd)
|
|
{
|
|
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pLoop == nullptr)
|
|
return false ;
|
|
if ( pLoop->GetType() != CRV_COMPO) {
|
|
if ( nCrv != 0)
|
|
return false ;
|
|
pLoop->SetTempProp( nProp, nPropInd) ;
|
|
return true ;
|
|
}
|
|
return GetBasicCurveComposite( pLoop)->SetCurveTempProp( nCrv, nProp, nPropInd) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd) const
|
|
{
|
|
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pLoop == nullptr)
|
|
return false ;
|
|
if ( pLoop->GetType() != CRV_COMPO) {
|
|
if ( nCrv != 0)
|
|
return false ;
|
|
nProp = pLoop->GetTempProp( nPropInd) ;
|
|
return true ;
|
|
}
|
|
return GetBasicCurveComposite( pLoop)->GetCurveTempProp( nCrv, nProp, nPropInd) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::ResetAllCurveTempProps( void)
|
|
{
|
|
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
|
|
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
|
|
ICurve* pLoop = GetMyLoop( nC, nL) ;
|
|
if ( pLoop != nullptr) {
|
|
if ( pLoop->GetType() != CRV_COMPO) {
|
|
pLoop->SetTempProp( 0, 0) ;
|
|
pLoop->SetTempProp( 0, 1) ;
|
|
}
|
|
else {
|
|
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
|
|
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
|
|
pCompoLoop->SetCurveTempProp( nI, 0, 0) ;
|
|
pCompoLoop->SetCurveTempProp( nI, 0, 1) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd)
|
|
{
|
|
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pLoop == nullptr)
|
|
return false ;
|
|
if ( pLoop->GetType() != CRV_COMPO) {
|
|
if ( nCrv != 0)
|
|
return false ;
|
|
pLoop->SetTempParam( dParam, nParamInd) ;
|
|
return true ;
|
|
}
|
|
return GetBasicCurveComposite( pLoop)->SetCurveTempParam( nCrv, dParam, nParamInd) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd) const
|
|
{
|
|
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
|
if ( pLoop == nullptr)
|
|
return false ;
|
|
if ( pLoop->GetType() != CRV_COMPO) {
|
|
if ( nCrv != 0)
|
|
return false ;
|
|
dParam = pLoop->GetTempParam( nParamInd) ;
|
|
return true ;
|
|
}
|
|
return GetBasicCurveComposite( pLoop)->GetCurveTempParam( nCrv, dParam, nParamInd) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfFlatRegion::ResetAllCurveTempParams( void)
|
|
{
|
|
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
|
|
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
|
|
ICurve* pLoop = GetMyLoop( nC, nL) ;
|
|
if ( pLoop != nullptr) {
|
|
if ( pLoop->GetType() != CRV_COMPO) {
|
|
pLoop->SetTempParam( 0, 0) ;
|
|
pLoop->SetTempParam( 0, 1) ;
|
|
}
|
|
else {
|
|
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
|
|
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
|
|
pCompoLoop->SetCurveTempParam( nI, 0, 0) ;
|
|
pCompoLoop->SetCurveTempParam( nI, 0, 1) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|