//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : OutTsc.cpp Data : 23.03.14 Versione : 1.5c9 // Contenuto : Implementazione della classe output Tsc. // // // // Modifiche : 23.03.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "OutTsc.h" #include "/EgtDev/Include/EGkGeoVector3d.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoFrame3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveBezier.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EgtStringConverter.h" using namespace std ; //---------------------------------------------------------------------------- OutTsc::OutTsc( void) { m_nId = 0 ; m_nGroup.push( 0) ; m_bOutCol = false ; } //---------------------------------------------------------------------------- OutTsc::~OutTsc( void) { Close() ; } //---------------------------------------------------------------------------- bool OutTsc::Open( const string& sOutTsc) { // apro il file m_ofFile.open( stringtoW( sOutTsc)) ; if ( ! m_ofFile.good()) return false ; // scrivo linee iniziali Start() ; New() ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::Close( void) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // scrivo linee finali End() ; // chiudo il file m_ofFile.close() ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::Start( void) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // inizializzazioni m_nId = 0 ; m_nGroup.top() = 0 ; m_bOutCol = false ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::End( void) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::New( void) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // emetto stringa m_ofFile << "NEW" << endl ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::Remark( const string& sRemark) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // emetto stringa m_ofFile << "// " << sRemark << endl ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::SetMaterial( double dRed, double dGreen, double dBlue) { m_bOutCol = true ; m_cCol.Set( dRed, dGreen, dBlue) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::PutMaterial( int nObjId, bool bGroup) { // se necessario emetto il materiale if ( m_bOutCol || bGroup) { m_ofFile << "MAT( " << ToString( nObjId) << ", (" << ToString( m_cCol) << "))" << endl ; if ( bGroup) m_bOutCol = false ; } return true ; } //---------------------------------------------------------------------------- bool OutTsc::PushGroup( void) { int nVal = ( m_nGroup.empty() ? 0 : m_nGroup.top()) ; m_nGroup.push( nVal) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::PopGroup( void) { if ( m_nGroup.size() <= 1) return false ; m_nGroup.pop() ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::NewGroup( int nLev) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // calcolo gruppo di appartenenza string sParent = (( nLev == 0) ? "$ROOT" : ToString( m_nGroup.top())) ; // incremento indice corrente ++ m_nId ; // assegno indice gruppo corrente m_nGroup.top() = m_nId ; // creo il gruppo del pezzo m_ofFile << "GR.XY( " << ToString( m_nGroup.top()) << ", " << sParent << ", (0,0,0))" << endl ; // emetto il materiale PutMaterial( m_nGroup.top(), true) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::NewGroupRef( const Frame3d& frFrame, int nLev) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // calcolo gruppo di appartenenza string sParent = (( nLev == 0) ? "$ROOT" : ToString( m_nGroup.top())) ; // incremento indice corrente ++ m_nId ; // assegno indice layer corrente m_nGroup.top() = m_nId ; // creo il gruppo del layer m_ofFile << "GR( " << ToString( m_nGroup.top()) << ", " << sParent << ", " ; m_ofFile << "((" << ToString( frFrame.Orig()) << "), " ; m_ofFile << "(" << ToString( frFrame.VersX()) << "), " ; m_ofFile << "(" << ToString( frFrame.VersY()) << "), " ; m_ofFile << "(" << ToString( frFrame.VersZ()) << ")))" << endl ; // emetto il materiale PutMaterial( m_nGroup.top(), true) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::PutCurrRef( void) { return Frame( Frame3d()) ; } //---------------------------------------------------------------------------- bool OutTsc::Vector( const Vector3d& vtV) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // verifico non sia praticamente nullo if ( vtV.IsSmall()) return true ; // incremento indice corrente ++ m_nId ; // emetto vettore m_ofFile << "V( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; m_ofFile << ToString( vtV) << ")" << endl ; // se necessario emetto il materiale PutMaterial( m_nId) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::Point( const Point3d& ptP) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // incremento indice corrente ++ m_nId ; // emetto punto m_ofFile << "P( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; m_ofFile << ToString( ptP) << ")" << endl ; // se necessario emetto il materiale PutMaterial( m_nId) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::Frame( const Frame3d& frF) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // incremento indice corrente ++ m_nId ; // emetto riferimento m_ofFile << "FR( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; m_ofFile << "((" << ToString( frF.Orig()) << "), " ; m_ofFile << "(" << ToString( frF.VersX()) << "), " ; m_ofFile << "(" << ToString( frF.VersY()) << "), " ; m_ofFile << "(" << ToString( frF.VersZ()) << ")))" << endl ; // non usa materiale return true ; } //---------------------------------------------------------------------------- bool OutTsc::Line2P( const Point3d& ptP1, const Point3d& ptP2) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // verifico non sia praticamente nulla if ( AreSamePointApprox( ptP1, ptP2)) return true ; // incremento indice corrente ++ m_nId ; // emetto linea m_ofFile << "CL( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; m_ofFile << "(" << ToString( ptP1) << "), (" << ToString( ptP2) << "))" << endl ; // se necessario emetto il materiale PutMaterial( m_nId) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::ArcCPA( const Point3d& ptCen, const Point3d& ptMed, double dAngCenDeg) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // calcolo il raggio e l'angolo iniziale double dRad ; double dAngIniDeg ; Vector3d( ptMed - ptCen).ToSpherical( &dRad, nullptr, &dAngIniDeg) ; dAngIniDeg -= 0.5 * dAngCenDeg ; // verifico non sia praticamente nulla if ( abs( dRad) < EPS_SMALL || abs( dAngCenDeg) < EPS_ANG_SMALL) return true ; // incremento indice corrente ++ m_nId ; // emetto arco m_ofFile << "CA.XY( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; m_ofFile << "(" << ToString( ptCen) << "), " << ToString( dRad) << ", " ; m_ofFile << ToString( dAngIniDeg) << ", " << ToString( dAngCenDeg) << ", 0)" << endl ; // se necessario emetto il materiale PutMaterial( m_nId) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::CircleCR( const Point3d& ptCen, double dRad) { // verifico sia aperto if ( ! m_ofFile.is_open()) return false ; // incremento indice corrente ++ m_nId ; // emetto circonferenza m_ofFile << "CA.CXY( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; m_ofFile << "(" << ToString( ptCen) << "), " << ToString( dRad) << ")" << endl ; // se necessario emetto il materiale PutMaterial( m_nId) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::ArcCurvOrTgOrNone( const CrvPointDiffGeom& oDiffG) { // curvatura if ( oDiffG.nStatus == CrvPointDiffGeom::NCRV && abs( oDiffG.dCurv) > EPS_ZERO) { // tratto di arco Point3d ptCen = oDiffG.ptP + oDiffG.vtN / oDiffG.dCurv ; bool bCCW = ( oDiffG.vtT ^ oDiffG.vtN).z > 0 ; double dAngCenDeg = ( bCCW ? 1 : -1) * 4 * oDiffG.dCurv * RADTODEG ; ArcCPA( ptCen, oDiffG.ptP, dAngCenDeg) ; // raggio Line2P( oDiffG.ptP, ptCen) ; } // altrimenti, tangente else if ( oDiffG.nStatus == CrvPointDiffGeom::TANG && ! oDiffG.vtT.IsSmall()) Line2P( oDiffG.ptP - oDiffG.vtT, oDiffG.ptP + oDiffG.vtT) ; // altrimenti cerchietto else CircleCR( oDiffG.ptP, 1) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::NormalOrNone( const CrvPointDiffGeom& oDiffG) { const double NORM_LEN = 10 ; // normale if ( oDiffG.nStatus == CrvPointDiffGeom::NCRV && abs( oDiffG.dCurv) > EPS_ZERO) { double dLen = min( NORM_LEN, 1 / oDiffG.dCurv) ; Line2P( oDiffG.ptP - NORM_LEN * oDiffG.vtN, oDiffG.ptP + dLen * oDiffG.vtN) ; } // segmento perpendicolare alla tangente else if ( oDiffG.nStatus == CrvPointDiffGeom::TANG && ! oDiffG.vtT.IsSmall()) { Vector3d vtN = oDiffG.vtT ^ Z_AX ; if ( ! vtN.Normalize()) { vtN = oDiffG.vtT ^ Y_AX ; vtN.Normalize() ; } Line2P( oDiffG.ptP - NORM_LEN * vtN, oDiffG.ptP + NORM_LEN * vtN) ; } // altrimenti cerchietto else CircleCR( oDiffG.ptP, 1) ; return true ; } //---------------------------------------------------------------------------- bool OutTsc::PutGeoObj( const IGeoObj* pGeoObj, int nFlag) { // GeoVector3d if ( pGeoObj->GetType() == GEO_VECT3D) { const IGeoVector3d* pGVector ; // recupero e controllo il vettore if ( ( pGVector = GetGeoVector3d( pGeoObj)) == nullptr) return false ; // eseguo output return Vector( pGVector->GetVector()) ; } // GeoPoint3d else if ( pGeoObj->GetType() == GEO_PNT3D) { const IGeoPoint3d* pGPoint ; // recupero e controllo il punto if ( ( pGPoint = GetGeoPoint3d( pGeoObj)) == nullptr) return false ; // eseguo output return Point( pGPoint->GetPoint()) ; } // GeoFrame3d else if ( pGeoObj->GetType() == GEO_FRAME3D) { const IGeoFrame3d* pGFrame ; // recupero e controllo il punto if ( ( pGFrame = GetGeoFrame3d( pGeoObj)) == nullptr) return false ; // eseguo output return Frame( pGFrame->GetFrame()) ; } // Curve (Line, Arc, Bezier, Composite) else if (( pGeoObj->GetType() & GEO_CURVE) != 0) { const ICurve* pCurve ; // recupero e controllo la curva if ( ( pCurve = GetCurve( pGeoObj)) == nullptr) return false ; // eseguo output return PutCurve( pCurve, nFlag) ; } else return true ; } //---------------------------------------------------------------------------- bool OutTsc::PutCurve( const ICurve* pCurve, int nFlag) { // ciclo per disegnare i segmenti Remark( "Curve") ; Point3d ptIni ; Point3d ptFin ; PolyLine PL ; pCurve->ApproxWithLines( 0.1, 5, ICurve::APL_SPECIAL, PL) ; for ( bool bFound = PL.GetFirstLine( ptIni, ptFin) ; bFound ; bFound = PL.GetNextLine( ptIni, ptFin)) Line2P( ptIni, ptFin) ; // se richieste tangenti e curvature if ( ( nFlag & 1) != 0) { // ciclo per disegnare le derivate e le curvature Remark( "Curve:Tangents+Der2") ; double dU ; bool bFirst = true ; for ( bool bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { // ricavo il punto, la tangente, la normale e la curvatura CrvPointDiffGeom oDiffG ; pCurve->GetPointDiffGeom( dU, ( bFirst ? ICurve::FROM_PLUS : ICurve::FROM_MINUS), oDiffG) ; bFirst = false ; // curvatura o tangente o niente ArcCurvOrTgOrNone( oDiffG) ; // se punto con possibili discontinuitą e non punto iniziale o finale di curva chiusa if ( oDiffG.nFlag == CrvPointDiffGeom::TO_VERIFY && ! ( pCurve->IsClosed() && ( pCurve->IsStartParam( dU) || pCurve->IsEndParam( dU)))) { // ricavo il punto, la tangente, la normale e la curvatura dall'intorno superiore CrvPointDiffGeom oDiffGs ; pCurve->GetPointDiffGeom( dU, ICurve::FROM_PLUS, oDiffGs) ; // se ci sono delle discontinuitą if ( ThereIsDiscontinuity( oDiffG, oDiffGs)) // emetto curvatura o tangente o niente ArcCurvOrTgOrNone( oDiffGs) ; } } } // se richieste normali if ( ( nFlag & 2) != 0) { // ciclo per disegnare le derivate e le curvature Remark( "Curve:Normals") ; double dU ; bool bFirst = true ; for ( bool bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { // ricavo il punto, la tangente, la normale e la curvatura CrvPointDiffGeom oDiffG ; pCurve->GetPointDiffGeom( dU, ( bFirst ? ICurve::FROM_PLUS : ICurve::FROM_MINUS), oDiffG) ; bFirst = false ; // curvatura o tangente o niente NormalOrNone( oDiffG) ; // se punto con possibili discontinuitą e non punto iniziale o finale di curva chiusa if ( oDiffG.nFlag == CrvPointDiffGeom::TO_VERIFY && ! ( pCurve->IsClosed() && ( pCurve->IsStartParam( dU) || pCurve->IsEndParam( dU)))) { // ricavo il punto, la tangente, la normale e la curvatura dall'intorno superiore CrvPointDiffGeom oDiffGs ; pCurve->GetPointDiffGeom( dU, ICurve::FROM_PLUS, oDiffGs) ; // se ci sono delle discontinuitą if ( ThereIsDiscontinuity( oDiffG, oDiffGs)) // normale o niente NormalOrNone( oDiffGs) ; } } } // se curva di Bezier e richiesto anche il poligono di controllo if ( pCurve->GetType() == CRV_BEZIER && ( nFlag & 4) != 0) PutPolygBez( *(GetCurveBezier( pCurve))) ; // se richiesto il box if ( ( nFlag & 8) != 0) { BBox3d b3B ; if ( pCurve->GetLocalBBox( b3B)) PutBBox( b3B) ; } return true ; } //---------------------------------------------------------------------------- bool OutTsc::PutPolygBez( const ICurveBezier& CrvBez) { int i ; Point3d ptIni ; Point3d ptFin ; // ciclo per disegnare il poligono di controllo Remark( "BezierPolygon") ; ptIni = CrvBez.GetControlPoint( 0) ; for ( i = 1 ; i <= CrvBez.GetDegree() ; ++ i) { ptFin = CrvBez.GetControlPoint( i) ; // disegno Line2P( ptIni, ptFin) ; // nuovo iniziale prende i valori del finale ptIni = ptFin ; } return true ; } //---------------------------------------------------------------------------- bool OutTsc::PutBBox( const BBox3d& b3B) { Point3d ptMin ; Point3d ptMax ; if ( b3B.GetMinMax( ptMin, ptMax)) { Remark( "BoundingBox") ; // se ridotto a un punto if ( AreSamePointApprox( ptMin, ptMax)) Point( ptMin) ; // se ridotto ad una linea else if ( (( ptMax.x - ptMin.x) < EPS_SMALL && ( ptMax.y - ptMin.y) < EPS_SMALL) || (( ptMax.y - ptMin.y) < EPS_SMALL && ( ptMax.z - ptMin.z) < EPS_SMALL) || (( ptMax.z - ptMin.z) < EPS_SMALL && ( ptMax.x - ptMin.x) < EPS_SMALL)) Line2P( ptMin, ptMax) ; // se ridotto ad un rettangolo nel piano XY else if ( ( ptMax.z - ptMin.z) < EPS_SMALL) { // giro a Zmin Line2P( Point3d( ptMin.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMin.y, ptMin.z)) ; Line2P( Point3d( ptMax.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMax.y, ptMin.z)) ; Line2P( Point3d( ptMax.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMax.y, ptMin.z)) ; Line2P( Point3d( ptMin.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMin.y, ptMin.z)) ; } // se ridotto ad un rettangolo nel piano YZ else if ( ( ptMax.x - ptMin.x) < EPS_SMALL) { // giro a Xmin Line2P( Point3d( ptMin.x, ptMin.y, ptMin.z), Point3d( ptMin.x, ptMax.y, ptMin.z)) ; Line2P( Point3d( ptMin.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMax.y, ptMax.z)) ; Line2P( Point3d( ptMin.x, ptMax.y, ptMax.z), Point3d( ptMin.x, ptMin.y, ptMax.z)) ; Line2P( Point3d( ptMin.x, ptMin.y, ptMax.z), Point3d( ptMin.x, ptMin.y, ptMin.z)) ; } // se ridotto ad un rettangolo nel piano ZX else if ( ( ptMax.y - ptMin.y) < EPS_SMALL) { // giro a Ymin Line2P( Point3d( ptMin.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMin.y, ptMin.z)) ; Line2P( Point3d( ptMax.x, ptMin.y, ptMax.z), Point3d( ptMax.x, ptMin.y, ptMax.z)) ; Line2P( Point3d( ptMax.x, ptMin.y, ptMax.z), Point3d( ptMin.x, ptMin.y, ptMax.z)) ; Line2P( Point3d( ptMin.x, ptMin.y, ptMax.z), Point3d( ptMin.x, ptMin.y, ptMin.z)) ; } // caso generico else { // giro a Zmin Line2P( Point3d( ptMin.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMin.y, ptMin.z)) ; Line2P( Point3d( ptMax.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMax.y, ptMin.z)) ; Line2P( Point3d( ptMax.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMax.y, ptMin.z)) ; Line2P( Point3d( ptMin.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMin.y, ptMin.z)) ; // giro a Zmax Line2P( Point3d( ptMin.x, ptMin.y, ptMax.z), Point3d( ptMax.x, ptMin.y, ptMax.z)) ; Line2P( Point3d( ptMax.x, ptMin.y, ptMax.z), Point3d( ptMax.x, ptMax.y, ptMax.z)) ; Line2P( Point3d( ptMax.x, ptMax.y, ptMax.z), Point3d( ptMin.x, ptMax.y, ptMax.z)) ; Line2P( Point3d( ptMin.x, ptMax.y, ptMax.z), Point3d( ptMin.x, ptMin.y, ptMax.z)) ; // giunzione tra i due giri Line2P( Point3d( ptMin.x, ptMin.y, ptMin.z), Point3d( ptMin.x, ptMin.y, ptMax.z)) ; Line2P( Point3d( ptMax.x, ptMin.y, ptMin.z), Point3d( ptMax.x, ptMin.y, ptMax.z)) ; Line2P( Point3d( ptMax.x, ptMax.y, ptMin.z), Point3d( ptMax.x, ptMax.y, ptMax.z)) ; Line2P( Point3d( ptMin.x, ptMax.y, ptMin.z), Point3d( ptMin.x, ptMax.y, ptMax.z)) ; } } return true ; }