//---------------------------------------------------------------------------- // EgalTech 2019-2019 //---------------------------------------------------------------------------- // File : ExtDimension.cpp Data : 27.12.19 Versione : 2.2a1 // Contenuto : Implementazione della classe Dimension ( quota). // // // // Modifiche : 27.12.19 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ExtDimension.h" #include "GeoConst.h" #include "GeoObjFactory.h" #include "NgeWriter.h" #include "NgeReader.h" #include "FontManager.h" #include "FontAux.h" #include "CurveArc.h" #include "IntersLineLine.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkCurve.h" #include #include using namespace std ; //---------------------------------------------------------------------------- static const string IS_MEASURE = "<>" ; static const double STD_EXTLINELEN = 5.0 ; static const double MIN_EXTLINELEN = 0.1 ; static const double STD_ARROWLEN = 5.0 ; static const double MIN_ARROWLEN = 0.1 ; static const double STD_TEXTDIST = 2.0 ; static const double MIN_TEXTDIST = 0.1 ; static const int STD_DECDIGIT = -2 ; static const int MAX_DECDIGIT = 6 ; static const string STD_FONT = "ModernPropS.Nfe" ; static const double STD_TEXTHEIGHT = 10.0 ; static const double MIN_TEXTHEIGHT = 1.0 ; //---------------------------------------------------------------------------- GEOOBJ_REGISTER( EXT_DIMENSION, NGE_E_DIM, ExtDimension) ; //---------------------------------------------------------------------------- ExtDimension::ExtDimension( void) : m_dExtLineLen( STD_EXTLINELEN), m_dArrowLen( STD_ARROWLEN), m_dTextDist( STD_TEXTDIST), m_bLenIsMM( true), m_nDecDigit( STD_DECDIGIT), m_sFont( STD_FONT), m_dTextHeight( STD_TEXTHEIGHT), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { } //---------------------------------------------------------------------------- ExtDimension::~ExtDimension( void) { } //---------------------------------------------------------------------------- bool ExtDimension::SetStyle( double dExtLineLen, double dArrowLen, double dTextDist, bool bLenIsMM, int nDecDigit, const string& sFont, double dTextHeight) { m_dExtLineLen = max( dExtLineLen, MIN_EXTLINELEN) ; m_dArrowLen = max( dArrowLen, MIN_ARROWLEN) ; m_dTextDist = max( dTextDist, MIN_TEXTDIST) ; m_bLenIsMM = bLenIsMM ; m_nDecDigit = Clamp( nDecDigit, -MAX_DECDIGIT, MAX_DECDIGIT) ; m_sFont = sFont ; m_dTextHeight = max( dTextHeight, MIN_TEXTHEIGHT) ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::SetLinear( const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptPos, const Vector3d& vtN, const Vector3d& vtDir, const string& sText) { // dichiaro quota non ancora determinata m_nType = DT_NONE ; // verifico la definizione del versore normale m_vtN = vtN ; if ( ! m_vtN.Normalize()) return false ; // porto i punti nel piano definito da P1 e N m_ptP1 = ptP1 ; m_ptP2 = ptP2 - ( ptP2 - m_ptP1) * m_vtN * m_vtN ; m_ptPos = ptPos - ( ptPos - m_ptP1) * m_vtN * m_vtN ; // verifico che i punti di misura non siano coincidenti if ( AreSamePointApprox( m_ptP1, m_ptP2)) return false ; // direzione di riferimento ( nel piano perpendicolare a vtN) m_vtDir = vtDir ; if ( m_vtDir.IsSmall()) m_vtDir = m_ptP2 - m_ptP1 ; else { m_vtDir -= m_vtDir * m_vtN * m_vtN ; if ( m_vtDir * ( m_ptP2 - m_ptP1) < 0) m_vtDir.Invert() ; } if ( ! m_vtDir.Normalize()) return false ; // punti estremi della linea di misura ed esterni delle linee di estremità Vector3d vtLine1 = m_vtDir ; vtLine1.Rotate( m_vtN, 0, 1) ; Vector3d vtLine2 = vtLine1 ; double dProSca1 = vtLine1 * ( m_ptPos - m_ptP1) ; double dProSca2 = vtLine2 * ( m_ptPos - m_ptP2) ; if ( dProSca1 < -EPS_SMALL) vtLine1.Invert() ; if ( dProSca2 < -EPS_SMALL) vtLine2.Invert() ; if ( abs( dProSca1) < EPS_SMALL) vtLine1 = vtLine2 ; if ( abs( dProSca2) < EPS_SMALL) vtLine2 = vtLine1 ; m_ptP5 = m_ptP1 + vtLine1 * ( m_ptPos - m_ptP1) * vtLine1 ; m_ptP6 = m_ptP2 + vtLine2 * ( m_ptPos - m_ptP2) * vtLine2 ; m_ptP3 = m_ptP5 + vtLine1 * m_dExtLineLen ; m_ptP4 = m_ptP6 + vtLine2 * m_dExtLineLen ; // assegnazione del testo m_sText = sText ; // assegno il tipo m_nType = DT_LINEAR ; // imposto da calcolare m_bToCalc = true ; m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::SetRadial( const Point3d& ptCen, const Point3d& ptPos, const Vector3d& vtN, const string& sText) { // il punto m_ptP6 viene utilizzato per il centro // dichiaro quota non ancora determinata m_nType = DT_NONE ; // verifico la definizione del versore normale e del versore X m_vtN = vtN ; m_vtDir = ptPos - ptCen ; if ( ! m_vtN.Normalize() || ! m_vtDir.Normalize()) return false ; // porto i punti nel piano definito da ptCen e vtN m_ptP6 = ptCen ; m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ; m_ptP1 = ptCen ; m_ptP5 = m_ptP1 ; m_ptP2 = m_ptPos ; // verifico che i punti di misura non siano coincidenti if ( AreSamePointApprox( m_ptP6, m_ptPos)) return false ; // assegnazione del testo m_sText = sText ; // assegno il tipo m_nType = DT_RADIAL ; // imposto da calcolare m_bToCalc = true ; m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::SetDiametral( const Point3d& ptCen, const Point3d& ptPos, const Vector3d& vtN, const string& sText) { // il punto m_ptP6 viene utilizzato per il centro // dichiaro quota non ancora determinata m_nType = DT_NONE ; // verifico la definizione del versore normale e del versore X m_vtN = vtN ; m_vtDir = ptPos - ptCen ; if ( ! m_vtN.Normalize() || ! m_vtDir.Normalize()) return false ; // porto i punti nel piano definito da ptP6 e vtN m_ptP6 = ptCen ; m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ; m_ptP2 = m_ptPos ; // ottengo il punto diametralmente opposto a ptPos m_ptP1 = ptCen - ( m_ptPos - ptCen) ; m_ptP5 = m_ptP1 ; // verifico che i punti di misura non siano coincidenti if ( AreSamePointApprox( m_ptP5, m_ptPos)) return false ; // assegnazione del testo m_sText = sText ; // assegno il tipo m_nType = DT_DIAMETRAL ; // imposto da calcolare m_bToCalc = true ; m_OGrMgr.Reset() ; return true; } //---------------------------------------------------------------------------- bool ExtDimension::SetAngular( const Point3d& ptV, const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptPos, const Vector3d& vtN, const string& sText) { // dichiaro quota non ancora determinata m_nType = DT_NONE ; // verifico la definizione del versore normale m_vtN = vtN ; if ( ! m_vtN.Normalize()) return false ; // porto i punti e le direzioni nel piano definito da V e N m_ptP6 = ptV ; m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ; m_vtDir = m_ptPos - m_ptP6 ; double dLenDir = m_vtDir.Len() ; Vector3d vtLine1 = OrthoCompo( ptP1 - m_ptP6, m_vtN) ; Vector3d vtLine2 = OrthoCompo( ptP2 - m_ptP6, m_vtN) ; // verifico che i punti di misura non siano coincidenti if ( ! vtLine1.Normalize() || ! vtLine2.Normalize() || dLenDir < EPS_SMALL) return false ; // controllo se è testo o se è la misura double dFactor ; if ( m_sCalcText.find( IS_MEASURE) != string::npos) { m_sCalcText = "300.00" ; double dHalfDist = GetTextHalfDist( m_ptPos) ; dFactor = 2.5 * dHalfDist ; m_sCalcText = "" ; } else { double dHalfDist = GetTextHalfDist( m_ptPos) ; dFactor = 2.5 * dHalfDist ; } // allungo m_vtDir se è troppo vicino al centro if ( m_vtDir.Len() < dFactor) { Vector3d vtDir_n = m_vtDir ; if ( ! vtDir_n.Normalize()) return false ; m_ptPos = m_ptP6 + dFactor * vtDir_n ; // ricalcolo m_vtDir m_vtDir = m_ptPos - m_ptP6 ; dLenDir = m_vtDir.Len() ; } // assegno gli altri punti notevoli della quotatura m_ptP1 = m_ptP6 ; m_ptP2 = m_ptP6 ; m_ptP5 = m_ptP6 + vtLine1 * dLenDir ; m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen) ; m_ptP4 = m_ptP6 + vtLine2 * ( dLenDir + m_dExtLineLen) ; // assegnazione del testo m_sText = sText ; // assegno il tipo m_nType = DT_ANGULAR ; // imposto da calcolare m_bToCalc = true ; m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::SetAngularEx( const Point3d& ptV1, const Point3d& ptP1, const Point3d& ptV2, const Point3d& ptP2, const Point3d& ptPos, const Vector3d& vtN, const string& sText) { // dichiaro quota non ancora determinata m_nType = DT_NONE ; // verifico la definizione del versore normale m_vtN = vtN ; if ( ! m_vtN.Normalize()) return false ; // calcolo l'intersezione tra le due linee CurveLine Line1 ; if ( ! Line1.Set( ptV1, ptP1) || ! Line1.SetExtrusion( m_vtN)) return false ; CurveLine Line2 ; if ( ! Line2.Set( ptV2, ptP2) || ! Line2.SetExtrusion( m_vtN)) return false ; IntersLineLine IntLL( Line1, Line2, false) ; IntCrvCrvInfo Info ; if ( ! IntLL.GetIntCrvCrvInfo( Info) || Info.bOverlap) return false ; Point3d ptV = Media( Info.IciA[0].ptI, Info.IciB[0].ptI) ; // porto i punti e le direzioni nel piano definito da V1 e N m_ptP6 = ptV ; m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ; m_vtDir = m_ptPos - m_ptP6 ; double dLenDir = m_vtDir.Len() ; Vector3d vtLine1 = OrthoCompo( ptP1 - m_ptP6, m_vtN) ; Vector3d vtLine2 = OrthoCompo( ptP2 - m_ptP6, m_vtN) ; // verifico che i punti di misura non siano coincidenti if ( ! vtLine1.Normalize() || ! vtLine2.Normalize() || dLenDir < EPS_SMALL) return false ; // controllo se è testo o se è la misura double dFactor ; if ( m_sCalcText.find( IS_MEASURE) != string::npos) { m_sCalcText = "300.00" ; double dHalfDist = GetTextHalfDist( m_ptPos) ; dFactor = 2.5 * dHalfDist ; m_sCalcText = "" ; } else { double dHalfDist = GetTextHalfDist( m_ptPos) ; dFactor = 2.5 * dHalfDist ; } // allungo m_vtDir se è troppo vicino al centro if ( m_vtDir.Len() < dFactor) { Vector3d vtDir_n = m_vtDir ; if ( ! vtDir_n.Normalize()) return false ; m_ptPos = m_ptP6 + dFactor * vtDir_n ; // ricalcolo m_vtDir m_vtDir = m_ptPos - m_ptP6 ; dLenDir = m_vtDir.Len() ; } // assegno gli altri punti notevoli della quotatura // se i ptV concidono con l'intersezione tra le linee le sposto leggermente verso l'altro punto di quel lato Point3d ptV1New = ptV1 ; Point3d ptV2New = ptV2 ; if ( AreSamePointApprox( ptV1, ptV)) { Vector3d vtDir1 ; Line1.GetStartDir( vtDir1) ; double dLen ; Line1.GetLength( dLen) ; dLen = max( min( 1., dLen/ 10), 0.01) ; ptV1New = ptV1 + vtDir1 * dLen ; } if ( AreSamePointApprox( ptV2, ptV)) { Vector3d vtDir2 ; Line2.GetStartDir( vtDir2) ; double dLen ; Line2.GetLength( dLen) ; dLen = max( min( 1., dLen/ 10), 0.01) ; ptV2New = ptV2 + vtDir2 * dLen ; } m_ptP1 = ptV1New - ( ptV1New - m_ptP6) * m_vtN * m_vtN ; m_ptP2 = ptV2New - ( ptV2New - m_ptP6) * m_vtN * m_vtN ; m_ptP5 = m_ptP6 + vtLine1 * dLenDir ; double dLen1 = Dist( m_ptP6, m_ptP1) ; m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen * ( dLen1 < dLenDir ? 1 : -1)) ; double dLen2 = Dist( m_ptP6, m_ptP2) ; m_ptP4 = m_ptP6 + vtLine2 * ( dLenDir + m_dExtLineLen * ( dLen2 < dLenDir ? 1 : -1)) ; // assegnazione del testo m_sText = sText ; // assegno il tipo m_nType = DT_ANGULAR ; // imposto da calcolare m_bToCalc = true ; m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- ExtDimension* ExtDimension::Clone( void) const { // alloco oggetto ExtDimension* pDim = new( nothrow) ExtDimension ; if ( pDim != nullptr) { if ( ! pDim->CopyFrom( *this)) { delete pDim ; return nullptr ; } } return pDim ; } //---------------------------------------------------------------------------- bool ExtDimension::CopyFrom( const IGeoObj* pGObjSrc) { const ExtDimension* pDim = GetBasicExtDimension( pGObjSrc) ; if ( pDim == nullptr) return false ; return CopyFrom( *pDim) ; } //---------------------------------------------------------------------------- bool ExtDimension::CopyFrom( const ExtDimension& clSrc) { if ( &clSrc == this) return true ; m_OGrMgr.Reset() ; m_nType = clSrc.m_nType ; m_vtN = clSrc.m_vtN ; m_vtDir = clSrc.m_vtDir ; m_ptP1 = clSrc.m_ptP1 ; m_ptP2 = clSrc.m_ptP2 ; m_ptP3 = clSrc.m_ptP3 ; m_ptP4 = clSrc.m_ptP4 ; m_ptP5 = clSrc.m_ptP5 ; m_ptP6 = clSrc.m_ptP6 ; m_ptPos = clSrc.m_ptPos ; m_sText = clSrc.m_sText ; m_bToCalc = clSrc.m_bToCalc ; m_sCalcText = clSrc.m_sCalcText ; m_ptCalcPos = clSrc.m_ptCalcPos ; m_bCalcArrowIn = clSrc.m_bCalcArrowIn ; m_bCalcTextOn = clSrc.m_bCalcTextOn ; m_ptCalcP7 = clSrc.m_ptCalcP7 ; m_ptCalcP8 = clSrc.m_ptCalcP8 ; m_dExtLineLen = clSrc.m_dExtLineLen ; m_dArrowLen = clSrc.m_dArrowLen ; m_dTextDist = clSrc.m_dTextDist ; m_bLenIsMM = clSrc.m_bLenIsMM ; m_nDecDigit = clSrc.m_nDecDigit ; m_sFont = clSrc.m_sFont ; m_dTextHeight = clSrc.m_dTextHeight ; m_nTempProp[0] = clSrc.m_nTempProp[0] ; m_nTempProp[1] = clSrc.m_nTempProp[1] ; m_dTempParam[0] = clSrc.m_dTempParam[0] ; m_dTempParam[1] = clSrc.m_dTempParam[1] ; return true ; } //---------------------------------------------------------------------------- GeoObjType ExtDimension::GetType( void) const { return static_cast( GEOOBJ_GETTYPE( ExtDimension)) ; } //---------------------------------------------------------------------------- const string& ExtDimension::GetTitle( void) const { static const string sTitle = "Dimension" ; return sTitle ; } //---------------------------------------------------------------------------- const string& ExtDimension::GetSubType( void) const { static const string vsSubType[] = { "None", "Linear", "Radial", "Diametral", "Angular"} ; if ( m_nType >= DT_NONE && m_nType <= DT_ANGULAR) return vsSubType[m_nType] ; else return vsSubType[0] ; } //---------------------------------------------------------------------------- bool ExtDimension::Dump( string& sOut, bool bMM, const char* szNewLine) const { // parametri sOut += GetSubType() + szNewLine ; sOut += "VN( " + ToString( m_vtN, 3) + ") " + szNewLine ; sOut += "VD( " + ToString( m_vtDir, 3) + ") " + szNewLine ; sOut += "P1( " + ToString( GetInUiUnits( m_ptP1, bMM), 3) + ") " + szNewLine ; sOut += "P2( " + ToString( GetInUiUnits( m_ptP2, bMM), 3) + ") " + szNewLine ; sOut += "P3( " + ToString( GetInUiUnits( m_ptP3, bMM), 3) + ") " + szNewLine ; sOut += "P4( " + ToString( GetInUiUnits( m_ptP4, bMM), 3) + ") " + szNewLine ; sOut += "P5( " + ToString( GetInUiUnits( m_ptP5, bMM), 3) + ") " + szNewLine ; sOut += "P6( " + ToString( GetInUiUnits( m_ptP6, bMM), 3) + ") " + szNewLine ; sOut += "Pos( " + ToString( GetInUiUnits( m_ptPos, bMM), 3) + ") " + szNewLine ; sOut += "Txt=" + m_sText + szNewLine ; sOut += "El=" + ToString( GetInUiUnits( m_dExtLineLen, bMM), 3) + " Al=" + ToString( GetInUiUnits( m_dArrowLen, bMM), 3) + " Td=" + ToString( GetInUiUnits( m_dTextDist, bMM), 3) + szNewLine ; sOut += "Mm=" + string( m_bLenIsMM ? "1" : "0") + " Dec=" + ToString( m_nDecDigit) + szNewLine ; sOut += "Fnt=" + m_sFont + " H=" + ToString( GetInUiUnits( m_dTextHeight, bMM), 3) + szNewLine ; return true ; } //---------------------------------------------------------------------------- int ExtDimension::GetNgeId( void) const { return GEOOBJ_GETNGEID( ExtDimension) ; } //---------------------------------------------------------------------------- bool ExtDimension::Save( NgeWriter& ngeOut) const { // tipo if ( ! ngeOut.WriteInt( m_nType, ";", true)) return false ; // versori normale e direzione if ( ! ngeOut.WriteVector( m_vtN, ";")) return false ; if ( ! ngeOut.WriteVector( m_vtDir, ";", true)) return false ; // punti di quotatura if ( ! ngeOut.WritePoint( m_ptP1, ";")) return false ; if ( ! ngeOut.WritePoint( m_ptP2, ";")) return false ; if ( ! ngeOut.WritePoint( m_ptP3, ";")) return false ; if ( ! ngeOut.WritePoint( m_ptP4, ";", true)) return false ; if ( ! ngeOut.WritePoint( m_ptP5, ";")) return false ; if ( ! ngeOut.WritePoint( m_ptP6, ";")) return false ; if ( ! ngeOut.WritePoint( m_ptPos, ";", true)) return false ; // testo if ( ! ngeOut.WriteString( m_sText, ";", true)) return false ; // attributi if ( ! ngeOut.WriteDouble( m_dExtLineLen, ",")) return false ; if ( ! ngeOut.WriteDouble( m_dArrowLen, ",")) return false ; if ( ! ngeOut.WriteDouble( m_dTextDist, ",")) return false ; if ( ! ngeOut.WriteBool( m_bLenIsMM, ",")) return false ; if ( ! ngeOut.WriteInt( m_nDecDigit, ",")) return false ; if ( ! ngeOut.WriteString( m_sFont, ",")) return false ; if ( ! ngeOut.WriteDouble( m_dTextHeight, ";", true)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::Load( NgeReader& ngeIn) { // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; // leggo la prossima linea : tipo if ( ! ngeIn.ReadInt( m_nType, ";", true)) return false ; // leggo la prossima linea : versori normale e direzione if ( ! ngeIn.ReadVector( m_vtN, ";")) return false ; if ( ! ngeIn.ReadVector( m_vtDir, ";", true)) return false ; // leggo la prossima linea : punti di quotatura if ( ! ngeIn.ReadPoint( m_ptP1, ";")) return false ; if ( ! ngeIn.ReadPoint( m_ptP2, ";")) return false ; if ( ! ngeIn.ReadPoint( m_ptP3, ";")) return false ; if ( ! ngeIn.ReadPoint( m_ptP4, ";", true)) return false ; if ( ! ngeIn.ReadPoint( m_ptP5, ";")) return false ; if ( ! ngeIn.ReadPoint( m_ptP6, ";")) return false ; if ( ! ngeIn.ReadPoint( m_ptPos, ";", true)) return false ; // leggo la prossima linea : testo if ( ! ngeIn.ReadString( m_sText, ";", true)) return false ; // leggo la prossima linea : attributi if ( ! ngeIn.ReadDouble( m_dExtLineLen, ",")) return false ; if ( ! ngeIn.ReadDouble( m_dArrowLen, ",")) return false ; if ( ! ngeIn.ReadDouble( m_dTextDist, ",")) return false ; if ( ! ngeIn.ReadBool( m_bLenIsMM, ",")) return false ; if ( ! ngeIn.ReadInt( m_nDecDigit, ",")) return false ; if ( ! ngeIn.ReadString( m_sFont, ",")) return false ; if ( ! ngeIn.ReadDouble( m_dTextHeight, ";", true)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::GetLocalBBox( BBox3d& b3Loc, int nFlag) const { // eventuale ricalcolo Update() ; if ( m_nType == DT_LINEAR) { b3Loc.Set( m_ptP1) ; b3Loc.Add( m_ptP2) ; b3Loc.Add( m_ptP3) ; b3Loc.Add( m_ptP4) ; b3Loc.Add( m_ptCalcP7) ; b3Loc.Add( m_ptCalcP8) ; // ingombro del testo BBox3d b3Text ; if ( GetTextLocalBBox( b3Text)) b3Loc.Add( b3Text) ; return true ; } else if ( m_nType == DT_RADIAL) { b3Loc.Set( m_ptP6) ; b3Loc.Add( m_ptPos) ; // ingombro del testo BBox3d b3Text ; if ( GetTextLocalBBox( b3Text)) b3Loc.Add( b3Text) ; return true ; } else if ( m_nType == DT_DIAMETRAL) { b3Loc.Set( m_ptP6) ; b3Loc.Add( m_ptPos) ; // ingombro del testo BBox3d b3Text ; if ( GetTextLocalBBox( b3Text)) b3Loc.Add( b3Text) ; return true ; } else if ( m_nType == DT_ANGULAR) { b3Loc.Add( m_ptP1) ; b3Loc.Add( m_ptP2) ; b3Loc.Add( m_ptP3) ; b3Loc.Add( m_ptP4) ; b3Loc.Set( m_ptP5) ; b3Loc.Set( m_ptP6) ; b3Loc.Add( m_ptCalcP7) ; b3Loc.Add( m_ptCalcP8) ; // ingombro del testo BBox3d b3Text ; if ( GetTextLocalBBox( b3Text)) b3Loc.Add( b3Text) ; return true ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const { // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; // eventuale ricalcolo Update() ; // se valido if ( m_nType == DT_LINEAR) { // ingombro dei punti ( portati nel riferimento passato) Point3d ptFrP1 = m_ptP1 ; ptFrP1.ToGlob( frRef) ; b3Ref.Set( ptFrP1) ; Point3d ptFrP2 = m_ptP2 ; ptFrP2.ToGlob( frRef) ; b3Ref.Add( ptFrP2) ; Point3d ptFrP3 = m_ptP3 ; ptFrP3.ToGlob( frRef) ; b3Ref.Add( ptFrP3) ; Point3d ptFrP4 = m_ptP4 ; ptFrP4.ToGlob( frRef) ; b3Ref.Add( ptFrP4) ; Point3d ptFrP7 = m_ptCalcP7 ; ptFrP7.ToGlob( frRef) ; b3Ref.Add( ptFrP7) ; Point3d ptFrP8 = m_ptCalcP8 ; ptFrP8.ToGlob( frRef) ; b3Ref.Add( ptFrP8) ; // ingombro del testo BBox3d b3Text ; if ( GetTextBBox( frRef, b3Text)) b3Ref.Add( b3Text) ; return true ; } else if ( m_nType == DT_RADIAL) { // ingombro dei punti ( portati nel riferimento passato) Point3d ptFrP5 = m_ptP6 ; ptFrP5.ToGlob( frRef) ; b3Ref.Set( ptFrP5) ; Point3d ptFrPos = m_ptPos ; ptFrPos.ToGlob( frRef) ; b3Ref.Set( ptFrPos) ; // ingombro del testo BBox3d b3Text ; if ( GetTextBBox( frRef, b3Text)) b3Ref.Add( b3Text) ; return true ; } else if ( m_nType == DT_DIAMETRAL) { // ingombro dei punti ( portati nel riferimento passato) Point3d ptFrP5 = m_ptP6 ; ptFrP5.ToGlob( frRef) ; b3Ref.Set( ptFrP5) ; Point3d ptFrPos = m_ptPos ; ptFrPos.ToGlob( frRef) ; b3Ref.Set( ptFrPos) ; // ingombro del testo BBox3d b3Text ; if ( GetTextBBox( frRef, b3Text)) b3Ref.Add( b3Text) ; return true ; } else if ( m_nType == DT_ANGULAR) { Point3d ptFrP1 = m_ptP1 ; ptFrP1.ToGlob( frRef) ; b3Ref.Add( ptFrP1) ; Point3d ptFrP2 = m_ptP2 ; ptFrP2.ToGlob( frRef) ; b3Ref.Add( ptFrP2) ; Point3d ptFrP3 = m_ptP3 ; ptFrP3.ToGlob( frRef) ; b3Ref.Add( ptFrP3) ; Point3d ptFrP4 = m_ptP4 ; ptFrP4.ToGlob( frRef) ; b3Ref.Add( ptFrP4) ; Point3d ptFrP5 = m_ptP5 ; ptFrP5.ToGlob( frRef) ; b3Ref.Set( ptFrP5) ; Point3d ptFrP6 = m_ptP6 ; ptFrP6.ToGlob( frRef) ; b3Ref.Set( ptFrP6) ; Point3d ptFrP7 = m_ptCalcP7 ; ptFrP7.ToGlob( frRef) ; b3Ref.Add( ptFrP7) ; Point3d ptFrP8 = m_ptCalcP8 ; ptFrP8.ToGlob( frRef) ; b3Ref.Add( ptFrP8) ; // ingombro del testo BBox3d b3Text ; if ( GetTextBBox( frRef, b3Text)) b3Ref.Add( b3Text) ; return true ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::Translate( const Vector3d& vtMove) { // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { m_ptP1.Translate( vtMove) ; m_ptP2.Translate( vtMove) ; m_ptP3.Translate( vtMove) ; m_ptP4.Translate( vtMove) ; m_ptP5.Translate( vtMove) ; m_ptP6.Translate( vtMove) ; m_ptPos.Translate( vtMove) ; return true ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { return ( m_vtN.Rotate( vtAx, dCosAng, dSinAng) && m_vtDir.Rotate( vtAx, dCosAng, dSinAng) && m_ptP1.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_ptP2.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_ptP3.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_ptP4.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_ptP5.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_ptP6.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_ptPos.Rotate( ptAx, vtAx, dCosAng, dSinAng)) ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // sistemo i vettori Vector3d vtTmp = m_vtN ^ m_vtDir ; if ( ! vtTmp.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) || ! vtTmp.Normalize()) return false ; if ( ! m_vtDir.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) || ! m_vtDir.Normalize()) return false ; m_vtN = m_vtDir ^ vtTmp ; if ( ! m_vtN.Normalize()) return false ; // scalo i punti di base if ( ! m_ptP1.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ)) return false ; if ( ! m_ptP2.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ)) return false ; if ( ! m_ptP6.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ)) return false ; if ( ! m_ptPos.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ)) return false ; // ricalcolo completamente la quota switch ( m_nType) { case DT_LINEAR : return SetLinear( m_ptP1, m_ptP2, m_ptPos, m_vtN, m_vtDir, m_sText) ; case DT_RADIAL : return SetRadial( m_ptP6, m_ptPos, m_vtN, m_sText) ; case DT_DIAMETRAL : return SetDiametral( m_ptP6, m_ptPos, m_vtN, m_sText) ; case DT_ANGULAR : return SetAngular( m_ptP1, m_ptP6, m_ptP2, m_ptPos, m_vtN, m_sText) ; default : return false ; } } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // eseguo il mirror dei versori if ( ! m_vtN.Mirror( vtNorm)) return false ; if ( ! m_vtDir.Mirror( vtNorm)) return false ; // eseguo il mirror dei punti if ( ! m_ptP1.Mirror( ptOn, vtNorm)) return false ; if ( ! m_ptP2.Mirror( ptOn, vtNorm)) return false ; if ( ! m_ptP3.Mirror( ptOn, vtNorm)) return false ; if ( ! m_ptP4.Mirror( ptOn, vtNorm)) return false ; if ( ! m_ptP5.Mirror( ptOn, vtNorm)) return false ; if ( ! m_ptP6.Mirror( ptOn, vtNorm)) return false ; if ( ! m_ptPos.Mirror( ptOn, vtNorm)) return false ; return true ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) { // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // sistemo i vettori Vector3d vtTmp = m_vtN ^ m_vtDir ; if ( ! vtTmp.Shear( vtNorm, vtDir, dCoeff) || ! vtTmp.Normalize()) return false ; if ( ! m_vtDir.Shear( vtNorm, vtDir, dCoeff) || ! m_vtDir.Normalize()) return false ; m_vtN = m_vtDir ^ vtTmp ; if ( ! m_vtN.Normalize()) return false ; // eseguo scorrimento dei punti di base if ( ! m_ptP1.Shear( ptOn, vtNorm, vtDir, dCoeff)) return false ; if ( ! m_ptP2.Shear( ptOn, vtNorm, vtDir, dCoeff)) return false ; if ( ! m_ptP6.Shear( ptOn, vtNorm, vtDir, dCoeff)) return false ; if ( ! m_ptPos.Shear( ptOn, vtNorm, vtDir, dCoeff)) return false ; // ricalcolo completamente la quota switch ( m_nType) { case DT_LINEAR : return SetLinear( m_ptP1, m_ptP2, m_ptPos, m_vtN, m_vtDir, m_sText) ; case DT_RADIAL : return SetRadial( m_ptP6, m_ptPos, m_vtN, m_sText) ; case DT_DIAMETRAL : return SetDiametral( m_ptP6, m_ptPos, m_vtN, m_sText) ; case DT_ANGULAR : return SetAngular( m_ptP1, m_ptP6, m_ptP2, m_ptPos, m_vtN, m_sText) ; default : return false ; } } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::ToGlob( const Frame3d& frRef) { // 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 m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori return ( m_vtN.ToGlob( frRef) && m_vtDir.ToGlob( frRef) && m_ptP1.ToGlob( frRef) && m_ptP2.ToGlob( frRef) && m_ptP3.ToGlob( frRef) && m_ptP4.ToGlob( frRef) && m_ptP5.ToGlob( frRef) && m_ptP6.ToGlob( frRef) && m_ptPos.ToGlob( frRef)) ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::ToLoc( const Frame3d& frRef) { // 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 m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori return ( m_vtN.ToLoc( frRef) && m_vtDir.ToLoc( frRef) && m_ptP1.ToLoc( frRef) && m_ptP2.ToLoc( frRef) && m_ptP3.ToLoc( frRef) && m_ptP4.ToLoc( frRef) && m_ptP5.ToLoc( frRef) && m_ptP6.ToLoc( frRef) && m_ptPos.ToLoc( frRef)) ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { // 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 m_bToCalc = true ; m_OGrMgr.Reset() ; // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori return ( m_vtN.ToGlob( frOri) && m_vtN.ToLoc( frDest) && m_vtDir.ToGlob( frOri) && m_vtDir.ToLoc( frDest) && m_ptP1.ToGlob( frOri) && m_ptP1.ToLoc( frDest) && m_ptP2.ToGlob( frOri) && m_ptP2.ToLoc( frDest) && m_ptP3.ToGlob( frOri) && m_ptP3.ToLoc( frDest) && m_ptP4.ToGlob( frOri) && m_ptP4.ToLoc( frDest) && m_ptP5.ToGlob( frOri) && m_ptP5.ToLoc( frDest) && m_ptP6.ToGlob( frOri) && m_ptP6.ToLoc( frDest) && m_ptPos.ToGlob( frOri) && m_ptPos.ToLoc( frDest)) ; } else return false ; } //---------------------------------------------------------------------------- bool ExtDimension::Update( void) const { // se ricalcolo non richiesto, esco if ( ! m_bToCalc) return true ; // a seconda del tipo, ... switch ( m_nType) { case DT_LINEAR : { // testo m_sCalcText = m_sText ; if ( m_sCalcText.find( IS_MEASURE) != string::npos) { double dVal = ( m_ptP2 - m_ptP1) * m_vtDir * ( m_bLenIsMM ? 1 : 1. / ONEINCH) ; string sVal = ToString( dVal, m_nDecDigit) ; ReplaceString( m_sCalcText, IS_MEASURE, sVal) ; } // punto di inserimento del testo m_ptCalcPos = ( m_ptP5 + m_ptP6) / 2 ; // semidistanza di interruzione double dHalfDist = GetTextHalfDist( m_ptCalcPos) ; // lunghezza della linea di misura double dLen = ( m_ptP6 - m_ptP5).Len() ; // determino come orientare le frecce e dove mettere il testo if ( dLen - 2 * m_dArrowLen >= 2 * dHalfDist) { m_bCalcArrowIn = true ; m_ptCalcP7 = m_ptCalcPos - m_vtDir * dHalfDist ; m_ptCalcP8 = m_ptCalcPos + m_vtDir * dHalfDist ; } // le frecce stanno fuori ma il testo dentro else if ( dLen >= 2 * dHalfDist) { m_bCalcArrowIn = false ; m_ptCalcP7 = m_ptP5 - m_vtDir * 2 * m_dArrowLen ; m_ptCalcP8 = m_ptP6 + m_vtDir * 2 * m_dArrowLen ; } // stanno fuori sia le frecce sia il testo else { m_bCalcArrowIn = false ; m_ptCalcP7 = m_ptP5 - m_vtDir * 2 * m_dArrowLen ; m_ptCalcP8 = m_ptP6 + m_vtDir * 2 * m_dArrowLen ; // metto la quotatura dal lato di ptPos if ( ( m_ptPos - m_ptCalcP7).SqLen() <= ( m_ptPos - m_ptCalcP8).SqLen()) m_ptCalcPos = m_ptCalcP7 - m_vtDir * dHalfDist ; else m_ptCalcPos = m_ptCalcP8 + m_vtDir * dHalfDist ; } // dichiaro ricalcolo eseguito m_bToCalc = false ; return true ; } case DT_RADIAL : case DT_DIAMETRAL : { // testo m_sCalcText = m_sText ; if ( m_sCalcText.find( IS_MEASURE) != string::npos) { double dVal = 0 ; dVal = Dist( m_ptP1, m_ptP2) * ( m_bLenIsMM ? 1 : 1. / ONEINCH) ; string sVal = ToString( dVal, m_nDecDigit) ; if ( m_nType == DT_RADIAL) sVal = "R " + sVal ; else if ( m_nType == DT_DIAMETRAL) sVal = reinterpret_cast( u8"\u00D8") + sVal ; ReplaceString( m_sCalcText, IS_MEASURE, sVal) ; } // punto di inserimento del testo m_ptCalcPos = ( m_ptP5 + m_ptP2) / 2 ; // alzo il testo dalla linea di misura BBox3d b3Text ; if ( ! GetTextMyBBox( b3Text) && ! b3Text.IsEmpty()) return false ; double dHeight = b3Text.GetMax().y - b3Text.GetMin().y ; double dLength = b3Text.GetMax().x - b3Text.GetMin().x ; Vector3d vtPerpDir = m_ptPos - m_ptP6 ; if ( ! vtPerpDir.Normalize()) return false ; // calcolo il frame dell'arco per valutare la posizione del testo Frame3d frRef ; if ( ! frRef.Set( m_ptP6, m_vtN)) return false ; double dAngDeg = 0 ; if ( ! m_vtDir.GetAngle( frRef.VersX(), dAngDeg) || ! vtPerpDir.Rotate( m_vtN, ( dAngDeg < 90 ? 90 : -90))) return false ; m_ptCalcPos = m_ptCalcPos + 0.6 * dHeight * vtPerpDir ; // semidistanza di interruzione double dHalfDist = GetTextHalfDist( m_ptCalcPos, false) ; // lunghezza della linea di misura double dLen = Dist( m_ptP1, m_ptP2) ; // determino come orientare le frecce e dove mettere il testo if ( dLen - 2 * m_dArrowLen >= 2 * dHalfDist) { m_bCalcArrowIn = true ; m_bCalcTextOn = true ; m_ptCalcP7 = m_ptCalcPos - m_vtDir * dHalfDist ; m_ptCalcP8 = m_ptCalcPos + m_vtDir * dHalfDist ; } // le frecce stanno fuori ma il testo dentro else if ( dLen >= 2 * dHalfDist) { m_bCalcArrowIn = false ; m_bCalcTextOn = true ; m_ptCalcP7 = m_ptP5 - m_vtDir * 2 * m_dArrowLen ; m_ptCalcP8 = m_ptP2 + m_vtDir * 2 * m_dArrowLen ; } // stanno fuori sia le frecce sia il testo else { m_bCalcArrowIn = false ; m_bCalcTextOn = false ; // metto la quotatura dal lato di ptPos Vector3d vtRad = m_ptPos - m_ptP5 ; if ( ! vtRad.Normalize()) return false ; m_ptCalcPos = m_ptPos + vtRad * ( 2 * m_dArrowLen + m_dTextDist) ; const double COMP_LIM = 0.1 ; // circa 5.7deg if ( vtRad.x > COMP_LIM) m_ptCalcPos += dLength / 2 * X_AX ; else if ( vtRad.x < -COMP_LIM) m_ptCalcPos -= dLength / 2 * X_AX ; if ( vtRad.y > COMP_LIM) m_ptCalcPos += dHeight / 2 * Y_AX ; else if ( vtRad.y < -COMP_LIM) m_ptCalcPos -= dHeight / 2 * Y_AX ; } // dichiaro ricalcolo eseguito m_bToCalc = false ; return true ; } case DT_ANGULAR : { // angolo double dAngDeg, dAngDeg1, dAngDeg2 = 0 ; Vector3d vtLine1 = m_ptP3 - m_ptP6 ; Vector3d vtLine2 = m_ptP4 - m_ptP6 ; Vector3d vtLine3 = m_ptPos - m_ptP6 ; // calcolo gli angoli tra m_ptPos e i due punti che identificano i lati dell'angolo // per capire se sto calcolando l'angolo interno o esterno if ( ! vtLine1.GetAngle( vtLine2, dAngDeg) || ! vtLine1.GetAngle( vtLine3, dAngDeg1) || ! vtLine2.GetAngle( vtLine3, dAngDeg2)) return false ; if ( dAngDeg < dAngDeg1 + dAngDeg2 - EPS_SMALL || dAngDeg > dAngDeg1 + dAngDeg2 + EPS_SMALL) dAngDeg = 360 - dAngDeg ; // testo m_sCalcText = m_sText ; if ( m_sCalcText.find( IS_MEASURE) != string::npos) { string sAngDeg = ToString( dAngDeg, m_nDecDigit) ; ReplaceString( m_sCalcText, IS_MEASURE, sAngDeg + "°") ; } // calcolo ptP5_bis if ( ! vtLine2.Normalize()) return false ; Point3d ptP5_bis = m_ptP6 + m_vtDir.Len() * vtLine2 ; // calcolo l'arco su cui metterò la misura PtrOwner pCrvPos( CreateBasicCurveArc()) ; if ( IsNull( pCrvPos) || ! pCrvPos->Set3P( ptP5_bis, m_ptPos, m_ptP5, false)) return false ; // punto di inserimento del testo pCrvPos->GetMidPoint( m_ptCalcPos) ; // semidistanza di interruzione double dHalfDist = GetTextHalfDist( m_ptCalcPos) ; // lunghezza della linea di misura double dLen = 0 ; if ( ! pCrvPos->GetLength( dLen)) return false ; // calcolo anche lo spazio ad una distanza dal centro maggiorata double dDist = Dist( m_ptCalcPos, m_ptP6) ; double dLenPos = dDist * dAngDeg * DEGTORAD ; // determino come orientare le frecce e dove mettere il testo // frecce e testo dentro if ( dLen - 2 * m_dArrowLen >= 2 * dHalfDist) { m_bCalcArrowIn = true ; m_bCalcTextOn = true ; double dU ; pCrvPos->GetParamAtLength( dLen / 2. + dHalfDist, dU) ; pCrvPos->GetPointD1D2( dU, ICurve::FROM_MINUS, m_ptCalcP7) ; pCrvPos->GetParamAtLength( dLen / 2. - dHalfDist, dU) ; pCrvPos->GetPointD1D2( dU, ICurve::FROM_MINUS, m_ptCalcP8) ; } // le frecce stanno fuori ma il testo dentro // se allontanadomi dal centro il testo ci sta, allora mi allontano dal centro anziché metter il testo fuori else if ( dLen > 2 * dHalfDist || ( dLen < 2 * dHalfDist && dLenPos > 2 * dHalfDist)) { m_bCalcArrowIn = false ; m_bCalcTextOn = true ; double dU ; pCrvPos->GetParamAtLength( dLen / 2. + dHalfDist, dU) ; pCrvPos->GetPointD1D2( dU, ICurve::FROM_MINUS, m_ptCalcP7) ; pCrvPos->GetParamAtLength( dLen / 2. - dHalfDist, dU) ; pCrvPos->GetPointD1D2( dU, ICurve::FROM_MINUS, m_ptCalcP8) ; if ( dLen < 2 * dHalfDist) { m_ptCalcPos += ( m_ptCalcPos - m_ptP5) ; m_bCalcTextOn = false ; } } // stanno fuori sia le frecce sia il testo else { m_bCalcArrowIn = false ; m_bCalcTextOn = false ; vtLine1.Normalize() ; vtLine2.Normalize() ; if ( Dist( m_ptPos, m_ptP5) < Dist( m_ptPos, ptP5_bis)) { Vector3d vtDirEnd ; pCrvPos->GetEndDir( vtDirEnd) ; m_ptCalcPos = m_ptP5 + dHalfDist * ( vtDirEnd + vtLine1) ; } else { Vector3d vtDirStart ; pCrvPos->GetStartDir( vtDirStart) ; m_ptCalcPos = ptP5_bis + dHalfDist * ( - vtDirStart + vtLine2) ; } } // dichiaro ricalcolo eseguito m_bToCalc = false ; return true ; } default : return false ; } } //---------------------------------------------------------------------------- bool ExtDimension::GetMidPoint( Point3d& ptMid) const { // eventuale ricalcolo Update() ; switch ( m_nType) { case DT_LINEAR : case DT_RADIAL : case DT_DIAMETRAL: ptMid = ( m_ptP1 + m_ptP2) / 2; return true ; case DT_ANGULAR : { // calcolo ptP5_bis Vector3d vtLine2 = m_ptP2 - m_ptP6 ; double dLen2 = vtLine2.Len() ; if ( ! vtLine2.Normalize()) return false ; Point3d ptP5_bis = m_ptP2 + ( m_vtDir.Len() - dLen2) * vtLine2 ; Vector3d vtMid = ( ptP5_bis + m_ptP5) / 2 - m_ptP6 ; if ( ! vtMid.Normalize()) return false ; ptMid = m_ptP6 + vtMid * m_vtDir.Len() ; return true; } default : return false ; } } //---------------------------------------------------------------------------- bool ExtDimension::GetCenterPoint( Point3d& ptCen) const { // eventuale ricalcolo Update() ; // se valido switch ( m_nType) { case DT_LINEAR : ptCen = ( m_ptP5 + m_ptP6) / 2 ; return true ; case DT_RADIAL : case DT_DIAMETRAL : case DT_ANGULAR : ptCen = m_ptP6 ; return true ; default : return false ; } } //---------------------------------------------------------------------------- bool ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL) const { // eventuale ricalcolo Update() ; // se quota valida switch ( m_nType) { case DT_LINEAR : { // prima linea di riferimento lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP1) ; lstPL.back().AddUPoint( 1, m_ptP3) ; // seconda linea di riferimento lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP2) ; lstPL.back().AddUPoint( 1, m_ptP4) ; // se non c'è testo, linea di misura intera if ( IsEmptyOrSpaces( m_sCalcText)) { lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP5) ; lstPL.back().AddUPoint( 1, m_ptP6) ; } // altrimenti, linea di misura divisa in due parti else { // prima parte lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP5) ; lstPL.back().AddUPoint( 1, m_ptCalcP7) ; // seconda parte lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP6) ; lstPL.back().AddUPoint( 1, m_ptCalcP8) ; } // frecce lstPL.emplace_back() ; GetArrowHead( m_ptP5, ( m_bCalcArrowIn ? -m_vtDir : m_vtDir), lstPL.back()) ; lstPL.emplace_back() ; GetArrowHead( m_ptP6, ( m_bCalcArrowIn ? m_vtDir : -m_vtDir), lstPL.back()) ; // testo POLYLINELIST lstTxt; if ( ApproxTextWithLines( dLinTol, dAngTolDeg, lstTxt)) lstPL.splice( lstPL.end(), lstTxt) ; return true ; } case DT_RADIAL : case DT_DIAMETRAL : { // prima linea di riferimento lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP1) ; lstPL.back().AddUPoint( 1, m_ptP2) ; // freccia lstPL.emplace_back() ; Vector3d vtRad = m_ptPos - m_ptP6 ; vtRad.Normalize() ; GetArrowHead( m_ptP2, ( m_bCalcArrowIn ? vtRad : - vtRad), lstPL.back()) ; if ( ! m_bCalcArrowIn) { lstPL.emplace_back() ; Point3d ptArrowTail = m_ptP2 + vtRad * m_dArrowLen * 2 ; lstPL.back().AddUPoint( 0, m_ptP2) ; lstPL.back().AddUPoint( 1, ptArrowTail) ; } if ( m_nType == DT_DIAMETRAL) { lstPL.emplace_back() ; GetArrowHead( m_ptP5, ( m_bCalcArrowIn ? - vtRad : vtRad), lstPL.back()) ; if ( ! m_bCalcArrowIn) { lstPL.emplace_back() ; Point3d ptArrowTail = m_ptP5 - vtRad * m_dArrowLen * 2 ; lstPL.back().AddUPoint( 0, m_ptP5) ; lstPL.back().AddUPoint( 1, ptArrowTail) ; } } // testo POLYLINELIST lstTxt; if ( ApproxTextWithLines( dLinTol, dAngTolDeg, lstTxt)) lstPL.splice( lstPL.end(), lstTxt) ; return true ; } case DT_ANGULAR : { // prima linea di riferimento lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP1) ; lstPL.back().AddUPoint( 1, m_ptP3) ; // seconda linea di riferimento lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP2) ; lstPL.back().AddUPoint( 1, m_ptP4) ; // curva per l'arco PtrOwner pCrvPos( CreateBasicCurveArc()) ; if ( IsNull( pCrvPos)) return false ; // calcolo ptP5_bis Vector3d vtLine2 = m_ptP4 - m_ptP6 ; if ( ! vtLine2.Normalize()) return false ; Point3d ptP5_bis = m_ptP6 + m_vtDir.Len() * vtLine2 ; // approssimerò l'arco con una polyline PolyLine plApprox ; // se non ho testo if ( IsEmptyOrSpaces( m_sCalcText) || ! m_bCalcTextOn) { if ( ! pCrvPos->SetC2PN( m_ptP6, ptP5_bis, m_ptP5, m_vtN) || ! pCrvPos->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_STD, plApprox)) return false ; lstPL.emplace_back( plApprox) ; } // altrimenti, linea di misura divisa in due parti else { // prima parte if ( ! pCrvPos->SetC2PN( m_ptP6, m_ptP5, m_ptCalcP7, m_vtN) || ! pCrvPos->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_STD, plApprox)) return false ; lstPL.emplace_back( plApprox) ; // seconda parte if ( ! pCrvPos->SetC2PN( m_ptP6, ptP5_bis, m_ptCalcP8, m_vtN) || ! pCrvPos->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_STD, plApprox)) return false ; lstPL.emplace_back( plApprox) ; } // frecce if ( ! pCrvPos->Set3P( ptP5_bis, m_ptPos, m_ptP5, false)) return false ; Vector3d vtStartDir ; Vector3d vtEndDir ; pCrvPos->GetStartDir( vtStartDir) ; pCrvPos->GetEndDir( vtEndDir) ; //storto la punta delle frecce su una direzione mediata tra l'arco e la perpendicolare al lato double dFactor = 1 / ( 0.6 * m_vtDir.Len()) ;// questo fattore dipende direttamente dalla distanza di m_ptPos dal centro e smorza lo scostamento // se però le frecce sono fuori non le storto e faccio le code dritte anziché curvilinee if ( ! m_bCalcArrowIn) { Point3d ptArrowTail1, ptArrowTail2 ; ptArrowTail1 = m_ptP5 + vtEndDir * m_dArrowLen *2 ; lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, m_ptP5) ; lstPL.back().AddUPoint( 1, ptArrowTail1) ; ptArrowTail2 = ptP5_bis - vtStartDir * m_dArrowLen *2 ; lstPL.emplace_back() ; lstPL.back().AddUPoint( 0, ptP5_bis) ; lstPL.back().AddUPoint( 1, ptArrowTail2) ; dFactor = 0 ; } lstPL.emplace_back() ; Vector3d vtLine1 = m_ptP3 - m_ptP6 ; if ( ! vtLine1.Normalize()) return false ; GetArrowHead( m_ptP5, ( m_bCalcArrowIn ? vtEndDir : - vtEndDir) + vtLine1 * dFactor, lstPL.back()) ; lstPL.emplace_back() ; GetArrowHead( ptP5_bis, ( m_bCalcArrowIn ? - vtStartDir : vtStartDir) + vtLine2 * dFactor, lstPL.back()) ; // testo POLYLINELIST lstTxt ; if ( ApproxTextWithLines( dLinTol, dAngTolDeg, lstTxt)) lstPL.splice( lstPL.end(), lstTxt) ; return true ; } default: return false ; } } //---------------------------------------------------------------------------- double ExtDimension::GetTextHalfDist( const Point3d& ptText, bool bUseRot) const { // semi distanza di interruzione double dHalfDist = m_dTextHeight / 2 + m_dTextDist ; // recupero il box di ingombro del testo BBox3d b3Text ; if ( GetTextMyBBox( ptText, b3Text) && ! b3Text.IsEmpty()) { double dHalfL = ( b3Text.GetMax().x - b3Text.GetMin().x) / 2 ; double dHalfH = ( b3Text.GetMax().y - b3Text.GetMin().y) / 2 ; dHalfDist = sqrt( dHalfL * dHalfL + dHalfH * dHalfH) ; if ( bUseRot) { Vector3d vtDir = m_vtDir ; vtDir.Normalize() ; double dCoeff = ( dHalfH > 1 ? dHalfL / dHalfH : 0) ; if ( abs( vtDir.x) > dCoeff * abs( vtDir.y)) dHalfDist = min( dHalfDist, dHalfL / abs( vtDir.x)) ; else dHalfDist = min( dHalfDist, dHalfH / abs( vtDir.y)) ; } dHalfDist += m_dTextDist ; } return dHalfDist ; } //---------------------------------------------------------------------------- bool ExtDimension::GetArrowHead( const Point3d& ptTip, const Vector3d& vtDir, PolyLine& PL) const { Vector3d vtPerp = vtDir ^ m_vtN ; if ( ! vtPerp.Normalize()) return false ; const double A_WIDTH_COEFF = 0.1666 ; PL.AddUPoint( 0, ptTip) ; PL.AddUPoint( 1, ptTip - ( vtDir + vtPerp * A_WIDTH_COEFF) * m_dArrowLen) ; PL.AddUPoint( 2, ptTip - ( vtDir - vtPerp * A_WIDTH_COEFF) * m_dArrowLen) ; PL.AddUPoint( 4, ptTip) ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::SetCurrFont( FontManager& fntMgr) const { static const int FONT_WEIGHT = 400 ; static const bool FONT_ITALIC = false ; static const double FONT_RATIO = 0.75 ; static const double FONT_ADDADVANCE = 0 ; return fntMgr.SetCurrFont( m_sFont, FONT_WEIGHT, FONT_ITALIC, m_dTextHeight, FONT_RATIO, FONT_ADDADVANCE) ; } //---------------------------------------------------------------------------- bool ExtDimension::ApproxTextWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL) const { // eventuale ricalcolo Update() ; // se testo vuoto, risultato vuoto if ( IsEmptyOrSpaces( m_sCalcText)) return true ; // imposto il font corrente e i suoi dati FontManager& fntMgr = FontManager::GetFontManager() ; if ( ! SetCurrFont( fntMgr)) return false ; // richiedo l'outline if ( ! fntMgr.ApproxWithLines( m_sCalcText, ETXT_IPMC, dLinTol, dAngTolDeg, lstPL)) return false ; // calcolo la trasformazione Frame3d frRef ; if ( ! frRef.Set( m_ptCalcPos, m_vtN)) return false ; // oriento il testo con il raggio/diametro, ma solo se il testo è dentro la circonferenza if ( ( m_nType == DT_RADIAL || m_nType == DT_DIAMETRAL) && m_bCalcTextOn) { double dAngDeg = 0 ; m_vtDir.GetAngle( frRef.VersX(), dAngDeg) ; if ( ! frRef.Set( m_ptCalcPos, m_vtN, ( dAngDeg > 90 ? - m_vtDir : m_vtDir))) return false ; } // eseguo la trasformazione for ( auto& PL : lstPL) PL.ToGlob( frRef) ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::GetTextMyBBox( BBox3d& b3Loc) const { // imposto box vuoto b3Loc.Reset() ; // se testo vuoto, box vuoto if ( IsEmptyOrSpaces( m_sCalcText)) return true ; // imposto il font corrente e i suoi dati FontManager& fntMgr = FontManager::GetFontManager() ; if ( ! SetCurrFont( fntMgr)) return false ; // richiedo il box if ( ! fntMgr.GetBBox( m_sCalcText, ETXT_IPMC, b3Loc)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::GetTextMyBBox( const Point3d& ptPos, BBox3d& b3Loc) const { // determino il box del testo if ( ! GetTextMyBBox( b3Loc)) return false ; // calcolo ed eseguo la trasformazione Frame3d frRef ; if ( ! frRef.Set( ptPos, m_vtN)) return false ; b3Loc.ToGlob( frRef) ; return true ; } //---------------------------------------------------------------------------- bool ExtDimension::GetTextLocalBBox( BBox3d& b3Loc) const { // eventuale ricalcolo Update() ; // calcolo il box return GetTextMyBBox( m_ptCalcPos, b3Loc) ; } //---------------------------------------------------------------------------- bool ExtDimension::GetTextBBox( const Frame3d& frRef, BBox3d& b3Ref) const { // eventuale ricalcolo Update() ; // calcolo il box if ( ! GetTextMyBBox( m_ptCalcPos, b3Ref)) return false ; // porto il box nel riferimento passato b3Ref.ToGlob( frRef) ; return true ; }