//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1 // Contenuto : Implementazione di funzioni per creazione di superfici Stm // a partire da curve, con diversi metodi. // // // Modifiche : 01.02.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveArc.h" #include "CurveComposite.h" #include "SurfFlatRegion.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; //------------------------------------------------------------------------------- ISurfFlatRegion* GetSurfFlatRegionRectangle( double dWidth, double dLen) { // le dimensioni devono essere significative if ( dWidth < EPS_SMALL || dLen < EPS_SMALL) return nullptr ; // creo il contorno PolyLine PL ; PL.AddUPoint( 0, ORIG) ; PL.AddUPoint( 1, Point3d( dWidth, 0, 0)) ; PL.AddUPoint( 2, Point3d( dWidth, dLen, 0)) ; PL.AddUPoint( 3, Point3d( 0, dLen, 0)) ; PL.AddUPoint( 4, ORIG) ; PtrOwner pCC( CreateBasicCurveComposite()) ; if ( IsNull( pCC) || ! pCC->FromPolyLine( PL)) return nullptr ; // creo il rettangolo PtrOwner pSfr( CreateSurfFlatRegion()) ; if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pCC))) return nullptr ; else return Release( pSfr) ; } //------------------------------------------------------------------------------- ISurfFlatRegion* GetSurfFlatRegionStadium( double dWidth, double dLen) { // le dimensioni devono essere significative if ( dWidth < EPS_SMALL || dLen < EPS_SMALL) return nullptr ; // se dimensioni praticamente uguali, è un disco if ( fabs( dWidth - dLen) < 10 * EPS_SMALL) return GetSurfFlatRegionDisk( ( dWidth + dLen) / 4) ; // creo il contorno PolyArc PA ; if ( dWidth > dLen) { double dRad = dLen / 2 ; PA.AddUPoint( 0, Point3d( dRad, 0, 0), 0) ; PA.AddUPoint( 1, Point3d( dWidth - dRad, 0, 0), 1) ; PA.AddUPoint( 2, Point3d( dWidth - dRad, dLen, 0), 0) ; PA.AddUPoint( 3, Point3d( dRad, dLen, 0), 1) ; PA.AddUPoint( 4, Point3d( dRad, 0, 0), 0) ; } else { double dRad = dWidth / 2 ; PA.AddUPoint( 0, Point3d( dWidth, dRad, 0), 0) ; PA.AddUPoint( 1, Point3d( dWidth, dLen - dRad, 0), 1) ; PA.AddUPoint( 2, Point3d( 0, dLen - dRad, 0), 0) ; PA.AddUPoint( 3, Point3d( 0, dRad, 0), 1) ; PA.AddUPoint( 4, Point3d( dWidth, dRad, 0), 0) ; } PtrOwner pCC( CreateBasicCurveComposite()) ; if ( IsNull( pCC) || ! pCC->FromPolyArc( PA)) return nullptr ; // creo il rettangolo PtrOwner pSfr( CreateSurfFlatRegion()) ; if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pCC))) return nullptr ; else return Release( pSfr) ; } //------------------------------------------------------------------------------- ISurfFlatRegion* GetSurfFlatRegionDisk( double dRadius) { // le dimensioni devono essere significative if ( dRadius < EPS_SMALL) return nullptr ; // creo la circonferenza di riferimento PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; pArc->Set( ORIG, Z_AX, dRadius, X_AX, ANG_FULL, 0) ; // creo il disco PtrOwner pSfr( CreateSurfFlatRegion()) ; if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pArc))) return nullptr ; else return Release( pSfr) ; } //------------------------------------------------------------------------------- // Classe SurfFlatRegionByContours //------------------------------------------------------------------------------- SurfFlatRegionByContours::~SurfFlatRegionByContours(void) { // cancello eventuali curve rimaste for ( auto& pCrv : m_vpCrv) { if ( pCrv != nullptr) delete pCrv ; pCrv = nullptr ; } m_vpCrv.clear() ; } //------------------------------------------------------------------------------- bool SurfFlatRegionByContours::AddCurve( ICurve* pCrv) { // acquisisco la curva PtrOwner pMyCrv( pCrv) ; if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) return false ; // verifico sia chiusa if ( ! pMyCrv->IsClosed()) return false ; // la inserisco nel vettore delle curve m_vpCrv.push_back( Release( pMyCrv)) ; return true ; } //------------------------------------------------------------------------------- bool SurfFlatRegionByContours::Prepare( void) { // calcolo piano medio e area delle curve m_vArea.reserve( m_vpCrv.size()) ; Vector3d vtN0 ; for ( int i = 0 ; i < int( m_vpCrv.size()) ; ++ i) { // calcolo piano medio e area Plane3d plPlane ; double dArea ; if ( ! m_vpCrv[i]->GetArea( plPlane, dArea)) return false ; // imposto la normale del primo contorno come riferimento if ( i == 0) vtN0 = plPlane.vtN ; // verifico che le normali siano molto vicine if ( ! AreSameOrOppositeVectorApprox( plPlane.vtN, vtN0)) return false ; // assegno il segno all'area secondo il verso della normale if ( ( plPlane.vtN * vtN0) > 0) m_vArea.emplace_back( i, dArea) ; else m_vArea.emplace_back( i, - dArea) ; } // ordino in senso decrescente sull'area sort( m_vArea.begin(), m_vArea.end(), []( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ; return true ; } //------------------------------------------------------------------------------- ISurfFlatRegion* SurfFlatRegionByContours::GetSurf( void) { // se è la prima superficie, devo preparare if ( m_bFirst) { if ( ! Prepare()) return nullptr ; m_bFirst = false ; } // altrimenti, se ammessa una sola superficie errore else if ( ! m_bAllowedMore) { return nullptr ; } // creo la superficie PtrOwner pSfr( CreateBasicSurfFlatRegion()) ; if ( IsNull( pSfr)) return nullptr ; // aggiungo le diverse curve bool bFirstCrv ; do { bFirstCrv = true ; for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) { // recupero indice di percorso e verifico sia valido int j = m_vArea[i].first ; if ( j < 0) continue ; // la prima deve essere il loop esterno if ( bFirstCrv) { // ne faccio una copia PtrOwner pCrv( m_vpCrv[j]->Clone()) ; if ( IsNull( pCrv)) { m_vArea[i].first = - 1 ; continue ; } // provo a inserirla if ( pSfr->AddExtLoop( Release( pCrv))) { bFirstCrv = false ; delete m_vpCrv[j] ; m_vpCrv[j] = nullptr ; m_vArea[i].first = - 1 ; } } // gli altri sono loop interni else { // ne faccio una copia PtrOwner pCrv( m_vpCrv[j]->Clone()) ; if ( IsNull( pCrv)) { m_vArea[i].first = - 1 ; continue ; } // provo a inserirla if ( pSfr->AddIntLoop( Release( pCrv))) { delete m_vpCrv[j] ; m_vpCrv[j] = nullptr ; m_vArea[i].first = - 1 ; } } } } while ( m_bAllowedMultiChunk && ! bFirstCrv) ; // se non valida, errore if ( ! pSfr->IsValid()) return nullptr ; // restituisco la superficie return Release( pSfr) ; } //------------------------------------------------------------------------------- bool SurfFlatRegionByContours::AllCurvesUsed( void) { // verifico se sono rimaste delle curve for ( auto& pCrv : m_vpCrv) { if ( pCrv != nullptr) return false ; } return true ; } //------------------------------------------------------------------------------- bool SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId) { vId.clear() ; // verifico se sono rimaste delle curve for ( auto& pCrv : m_vpCrv) { if ( pCrv != nullptr) vId.push_back( pCrv->GetTempProp()) ; } return ( ! vId.empty()) ; }