//---------------------------------------------------------------------------- // EgalTech 2015-2023 //---------------------------------------------------------------------------- // File : Tool.cpp Data : 08.09.23 Versione : 2.5i1 // Contenuto : Implementazione della classe Tool // // // // Modifiche : 22.01.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" #include "CurveArc.h" #include "Tool.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkLinePntTgCurve.h" #include "/EgtDev/Include/EGkFilletChamfer.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EgtNumUtils.h" #include using namespace std ; //---------------------------------------------------------------------------- Tool::Tool( bool bApproxWithLines) : m_bApproxWithLines( bApproxWithLines), m_dLinTol( LIN_TOL_STD), m_dAngTolDeg( ANG_TOL_APPROX_DEG), m_nType( UNDEF), m_nCurrentNum( 0), m_dHeight( 0), m_dTipHeight( 0), m_dRadius( 0), m_dRCorner( 0), m_dTipRadius( 0), m_dRefRadius( 0), m_dCutterHeight( 0), m_dMrtChsWidth( 0), m_dMrtChsThickness( 0) { } //---------------------------------------------------------------------------- Tool::~Tool( void) { } //---------------------------------------------------------------------------- bool Tool::Clear( bool bApproxWithLines) { m_bApproxWithLines = bApproxWithLines ; m_dLinTol = LIN_TOL_STD ; m_dAngTolDeg = ANG_TOL_APPROX_DEG ; m_nType = UNDEF ; m_nCurrentNum = 0 ; m_dHeight = 0 ; m_dTipHeight = 0 ; m_dRadius = 0 ; m_dRCorner = 0 ; m_dTipRadius = 0 ; m_dRefRadius = 0 ; m_dMrtChsWidth = 0 ; m_dMrtChsThickness = 0 ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; return true ; } //---------- Tolleranza nell'approssimazione di curve profilo ---------------- //---------------------------------------------------------------------------- bool Tool::SetTolerances( double dLinTol, double dAngTolDeg) { m_dLinTol = max( dLinTol, LIN_TOL_MIN) ; m_dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ; return true ; } //---------------------------------------------------------------------------- bool Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, double dCutterH, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nCurrentNum = nToolNum ; m_nType = UNDEF ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; m_dCutterHeight = dCutterH ; // verifica sulle minime dimensioni globali if ( dH < EPS_SMALL || dR < EPS_SMALL || dCornR < - EPS_SMALL) return false ; bool bApproxWithLines = false ; // utensile cilindrico if ( dCornR < EPS_SMALL) { m_nType = CYLMILL ; m_dHeight = dH ; m_dRadius = dR ; m_dTipHeight = 0 ; m_dTipRadius = m_dRadius ; m_dRCorner = 0 ; m_dRefRadius = m_dRadius ; // profilo Point3d pt0( 0, 0, 0) ; Point3d pt1( m_dRadius, 0, 0) ; Point3d pt3( m_dRadius, - m_dHeight, 0) ; Point3d pt4( 0, - m_dHeight, 0) ; m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1); m_Outline.AddLine( pt3) ; m_Outline.AddLine( pt4) ; } // utensile naso di toro else if ( dCornR < dR - EPS_SMALL) { m_nType = BULLNOSEMILL ; m_dHeight = dH ; m_dRadius = dR ; m_dTipHeight = dCornR ; m_dTipRadius = dR - dCornR ; m_dRCorner = dCornR ; m_dRefRadius = m_dRadius ; // profilo Point3d pt0( 0, 0, 0) ; Point3d pt1( m_dRadius, 0, 0) ; Point3d pt2( m_dRadius, - m_dHeight + m_dTipHeight, 0) ; Point3d pt3( m_dTipRadius, - m_dHeight, 0) ; Point3d pt4( 0, - m_dHeight, 0) ; m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1); m_Outline.AddLine( pt2); m_Outline.AddArcTg( pt3) ; m_Outline.AddLine( pt4) ; // se da approssimare bApproxWithLines = m_bApproxWithLines ; } // utensile sferico else { m_nType = BALLMILL ; m_dHeight = dH ; m_dRadius = dR ; m_dTipHeight = m_dRadius ; m_dTipRadius = 0 ; m_dRCorner = m_dRadius ; m_dRefRadius = m_dRadius ; // profilo Point3d pt0( 0, 0, 0) ; Point3d pt1( m_dRadius, 0, 0) ; Point3d pt2( m_dRadius, - m_dHeight + m_dTipHeight, 0) ; Point3d pt4( 0, - m_dHeight, 0) ; m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1); m_Outline.AddLine( pt2); m_Outline.AddArcTg( pt4) ; } // eventuali sistemazioni per altezza tagliente if ( ModifyForCutterHeight() || bApproxWithLines) return SetGenTool( sToolName, &m_Outline, nToolNum) ; else return true ; } //---------------------------------------------------------------------------- bool Tool::SetAdvTool( const string& sToolName, double dH, double dR, double dTipH, double dTipR, double dCornR, double dCutterH, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nCurrentNum = nToolNum ; m_nType = UNDEF ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; m_dCutterHeight = dCutterH ; // Verifica dimensioni globali if ( dH < EPS_SMALL || dR < EPS_SMALL || dTipH < - EPS_SMALL || dTipR < - EPS_SMALL || dCornR < - EPS_SMALL) return false ; // Se altezza punta nulla, ricado nel caso standard if ( dTipH < EPS_SMALL || abs( dTipR - dR) < EPS_SMALL) return SetStdTool( sToolName, dH, dR, dCornR, dCutterH, nToolNum) ; // Caso avanzato m_dHeight = dH ; m_dRadius = dR ; m_dTipHeight = Clamp( dTipH, 0., dH) ; m_dTipRadius = max( dTipR, 0.) ; m_dRCorner = dCornR ; // Definisco il profilo Point3d pt0( 0, 0, 0) ; Point3d pt1( m_dRadius, 0, 0) ; Point3d pt2( m_dRadius, - m_dHeight + m_dTipHeight, 0) ; Point3d pt5( 0, - m_dHeight, 0) ; // Se raggio corner nullo, allora utensile conico if ( m_dRCorner < EPS_SMALL) { m_nType = CONEMILL ; m_dRCorner = 0 ; // Assegno il raggio di riferimento m_dRefRadius = m_dRadius * min( 1., m_dRadius / m_dTipHeight) ; // profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; m_Outline.AddLine( pt2) ; m_Outline.AddLine( Point3d( m_dTipRadius, - m_dHeight, 0)) ; m_Outline.AddLine( pt5) ; // eventuali sistemazioni per altezza tagliente if ( ModifyForCutterHeight()) return SetGenTool( sToolName, &m_Outline, nToolNum) ; else return true ; } // Altrimenti utensile generico // se Tip a punta ( TipRadius è raggio teorico della parte finale dell'utensile senza raccordo) if ( m_dTipRadius < m_dRadius) { // se punta a sfera if ( m_dTipRadius < EPS_SMALL) { // Assegno il raggio di riferimento m_dRefRadius = m_dRCorner ; // circonferenza del corner Point3d ptC( 0, - m_dHeight + m_dRCorner, 0) ; CurveArc cvCirc ; cvCirc.SetXY( ptC, m_dRCorner) ; // segmento tangente al corner da sopra o intersezione del gambo con il corner Point3d pt3 ; Point3d ptNear( ptC.x + m_dRCorner, ptC.y + m_dRCorner, 0) ; PtrOwner pLine( GetLinePointTgCurve( pt2, cvCirc, ptNear)) ; if ( ! IsNull( pLine)) pLine->GetEndPoint( pt3) ; else { double dSqDelta = m_dRCorner * m_dRCorner - m_dRadius * m_dRadius ; double dDelta = ( dSqDelta > DBL_EPSILON ? sqrt( dSqDelta) : 0.) ; pt2 = Point3d( m_dRadius, - m_dHeight + m_dRCorner + dDelta, 0) ; pt3 = pt2 ; } // creazione del corner Point3d pt4( 0, - m_dHeight, 0) ; CurveArc cvArc ; cvArc.SetC2P( ptC, pt3, pt4) ; // creazione curva composita m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; m_Outline.AddLine( pt2) ; m_Outline.AddLine( pt3) ; m_Outline.AddCurve( cvArc) ; m_Outline.AddLine( pt5) ; } // altrimenti punta a naso di toro else { // Assegno il raggio di riferimento m_dRefRadius = m_dTipRadius ; // punto da smussare con corner Point3d ptInt( m_dTipRadius, - m_dHeight, 0) ; // linea sopra il corner CurveLine cLine1 ; cLine1.Set( pt2, ptInt) ; // linea sotto il corner CurveLine cLine2 ; cLine2.Set( ptInt, pt5) ; // calcolo del corner Point3d ptIn1 = Media( pt2, ptInt, 0.5) ; Point3d ptIn2 = Media( ptInt, pt5, 0.5) ; double dTrim1, dTrim2 ; PtrOwner< ICurveArc> pArc( CreateFillet( cLine1, ptIn1, cLine2, ptIn2, Z_AX, m_dRCorner, dTrim1, dTrim2)) ; if ( IsNull( pArc)) return false ; Point3d pt3 ; pArc->GetStartPoint( pt3) ; // creazione curva composita m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; m_Outline.AddLine( pt2) ; m_Outline.AddLine( pt3) ; m_Outline.AddCurve( Release( pArc)) ; m_Outline.AddLine( pt5) ; } } // altrimenti Tip a coda di rondine ( TipRadius è raggio misurabile della parte finale dell'utensile) else { // il raggio della punta non può essere inferiore al raggio corner if ( m_dTipRadius < m_dRCorner) return false ; // Assegno il raggio di riferimento m_dRefRadius = m_dTipRadius ; // circonferenza del corner Point3d ptC( m_dTipRadius - m_dRCorner, - m_dHeight + m_dRCorner, 0) ; CurveArc cvCirc ; cvCirc.SetXY( ptC, m_dRCorner) ; // segmento tangente al corner da sopra Point3d ptNear( ptC.x + m_dRCorner, ptC.y + m_dRCorner, 0) ; PtrOwner pLine( GetLinePointTgCurve( pt2, cvCirc, ptNear)) ; if ( IsNull( pLine)) return false ; // creazione del corner Point3d pt3 ; pLine->GetEndPoint( pt3) ; Point3d pt4( ptC.x, - m_dHeight, 0) ; CurveArc cvArc ; cvArc.SetC2P( ptC, pt3, pt4) ; if ( cvArc.GetAngCenter() > 0) cvArc.ToExplementary() ; // creazione curva composita m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; m_Outline.AddLine( pt2) ; m_Outline.AddLine( pt3) ; m_Outline.AddCurve( cvArc) ; m_Outline.AddLine( pt5) ; } // eventuali sistemazioni per altezza tagliente ModifyForCutterHeight() ; return SetGenTool( sToolName, &m_Outline, nToolNum) ; } //---------------------------------------------------------------------------- bool Tool::ModifyForCutterHeight( void) { // Se altezza tagliente non definita o superiore alla altezza utensile non devo fare alcunché if ( m_dCutterHeight < EPS_SMALL || m_dCutterHeight > m_dHeight - EPS_SMALL) return false ; // quota di taglio double dYtrim = -m_dHeight + m_dCutterHeight ; // linea di taglio const double LEN_EXTRA = 10 ; CurveLine clTrim ; clTrim.SetPDL( Point3d( -LEN_EXTRA, dYtrim, 0), 0, max( m_dRadius, m_dTipRadius) + LEN_EXTRA) ; // intersezione con il profilo IntersCurveCurve intCC( m_Outline, clTrim) ; int nInters = intCC.GetIntersCount() ; if ( nInters > 0) { IntCrvCrvInfo aInfo ; intCC.GetIntCrvCrvInfo( nInters - 1, aInfo) ; double dU = ( aInfo.bOverlap ? aInfo.IciA[1].dU : aInfo.IciA[0].dU) ; m_Outline.TrimStartAtParam( dU) ; m_Outline.AddLine( Point3d( 0, dYtrim, 0), false) ; m_Outline.AddLine( ORIG, false) ; return true ; } return false ; } //---------------------------------------------------------------------------- bool Tool::SetSawTool( const string& sToolName, double dH, double dR, double dThick, double dStemR, double dCornR, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nType = UNDEF ; m_nCurrentNum = nToolNum ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; // Verifica dimensioni globali if ( dH < EPS_SMALL || dR < EPS_SMALL || dThick < EPS_SMALL || dStemR < - EPS_SMALL || dCornR < - EPS_SMALL) return false ; // Con gambo if ( dH > dThick) { // punti notevoli Point3d pt0( 0, 0, 0) ; Point3d pt1( dStemR, 0, 0) ; Point3d pt2( dStemR, - dH + dThick, 0) ; Point3d pt3( dR, - dH + dThick, 0) ; Point3d pt4( dR, - dH, 0) ; Point3d pt5( 0, - dH, 0) ; // senza raggio corner if ( dCornR < EPS_SMALL) { // creazione profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; m_Outline.AddLine( pt2) ; m_Outline.AddLine( pt3) ; m_Outline.AddLine( pt4) ; m_Outline.AddLine( pt5) ; } // altrimenti con raggio corner else { double dCR = Clamp( dCornR, 0., min( dThick / 2, dR - 10 * EPS_SMALL)) ; // creazione profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; m_Outline.AddLine( pt2) ; m_Outline.AddLine( pt3 - X_AX * dCR) ; m_Outline.AddArcTg( pt3 - Y_AX * dCR) ; m_Outline.AddLine( pt4 + Y_AX * dCR) ; m_Outline.AddArcTg( pt4 - X_AX * dCR) ; m_Outline.AddLine( pt5) ; } } // altrimenti senza gambo else { // punti notevoli Point3d pt0( 0, - dH + dThick, 0) ; Point3d pt3( dR, - dH + dThick, 0) ; Point3d pt4( dR, - dH, 0) ; Point3d pt5( 0, - dH, 0) ; // senza raggio corner if ( dCornR < EPS_SMALL) { // creazione profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt3) ; m_Outline.AddLine( pt4) ; m_Outline.AddLine( pt5) ; } // altrimenti con raggio corner else { double dCR = Clamp( dCornR, 0., min( dThick / 2, dR - 10 * EPS_SMALL)) ; // creazione profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt3 - X_AX * dCR) ; m_Outline.AddArcTg( pt3 - Y_AX * dCR) ; m_Outline.AddLine( pt4 + Y_AX * dCR) ; m_Outline.AddArcTg( pt4 - X_AX * dCR) ; m_Outline.AddLine( pt5) ; } } // Assegno il raggio di riferimento m_dRefRadius = dThick ; return SetGenTool( sToolName, &m_Outline, nToolNum) ; } //---------------------------------------------------------------------------- bool Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nType = UNDEF ; m_nCurrentNum = nToolNum ; if ( pToolOutline != &m_Outline) m_Outline.Clear() ; m_ArcLineApprox.Clear() ; // Copio il profilo e garantisco sia di soli archi e rette (converto eventuali curve di Bezier) if ( ! m_Outline.CopyFrom( pToolOutline) || ! m_Outline.ArcsBezierCurvesToArcsPerpExtr( m_dLinTol, m_dAngTolDeg)) return false ; // Ciclo sulle curve componenti const ICurve* pCurve = m_Outline.GetFirstCurve() ; while ( pCurve != nullptr) { // Se la curva è un arco ed è richiesto la verifica per l'approssimazione, // verifico se approssimarlo if ( m_bApproxWithLines && pCurve->GetType() == CRV_ARC) { // Centro e raggio dell'arco Point3d ptO = GetBasicCurveArc( pCurve)->GetCenter() ; double dRadius = GetBasicCurveArc( pCurve)->GetRadius() ; // Se il centro è fuori dall'asse devo approssimare bool bCurrApprox = ( abs( ptO.x) > EPS_SMALL) ; // Se una delle altre curve dista dal centro meno del raggio, devo approssimare for ( int nI = 0 ; ! bCurrApprox && nI < m_Outline.GetCurveCount() ; ++ nI) { const ICurve* pOtherCrv = m_Outline.GetCurve( nI) ; if ( pOtherCrv != pCurve) { DistPointCurve CalcDist( ptO, *pOtherCrv) ; double dCurrDist ; if ( CalcDist.GetDist( dCurrDist) && dCurrDist < dRadius - EPS_SMALL) bCurrApprox = true ; } } // Se devo approssimare if ( bCurrApprox) { // Creo la polyline approssimante PolyLine plyApprox ; if ( ! pCurve->ApproxWithLines( m_dLinTol, m_dAngTolDeg, ICurve::APL_SPECIAL, plyApprox)) return false ; // Aggiungo i segmenti di retta alla approssimazione Point3d ptEnd, ptTmp ; plyApprox.GetFirstPoint( ptEnd) ; double dEndU ; pCurve->GetParamAtPoint( ptEnd, dEndU) ; Vector3d vtTanArc, vtExtN ; pCurve->GetPointTang( dEndU, ICurve::FROM_MINUS, ptTmp, vtTanArc) ; vtExtN = - vtTanArc ^ Z_AX ; vtExtN.Normalize() ; m_vArcNormals.emplace_back( vtExtN) ; while ( plyApprox.GetNextPoint( ptEnd)) { m_ArcLineApprox.AddLine( ptEnd) ; pCurve->GetParamAtPoint( ptEnd, dEndU) ; pCurve->GetPointTang( dEndU, ICurve::FROM_MINUS, ptTmp, vtTanArc) ; vtExtN = - vtTanArc ^ Z_AX ; vtExtN.Normalize() ; m_vArcNormals.emplace_back( vtExtN) ; int nCvCount = m_ArcLineApprox.GetCurveCount() ; m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, int( m_vArcNormals.size()) - 1) ; } } // altrimenti lo aggiungo semplicemente else { m_ArcLineApprox.AddCurve( *pCurve, true) ; int nCvCount = m_ArcLineApprox.GetCurveCount() ; m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, - 1) ; } } // altrimenti è segmento e lo aggiungo semplicemente else m_ArcLineApprox.AddCurve( *pCurve, true) ; pCurve = m_Outline.GetNextCurve() ; } // Il profilo dell'utensile deve stare nel 1° e 4° quadrante del piano XY BBox3d Bounding ; m_Outline.GetLocalBBox( Bounding) ; if ( Bounding.GetMin().x < - 10 * EPS_SMALL) return false ; // Assegno il tipo dell'utensile m_nType = GEN ; // Assegno le dimensioni dell'utensile m_dHeight = - Bounding.GetMin().y ; m_dRadius = Bounding.GetMax().x ; // Assegno il raggio di riferimento se non già assegnato if ( m_dRefRadius < EPS_SMALL) m_dRefRadius = 0.25 * m_dRadius ; return true ; } //---------------------------------------------------------------------------- bool Tool::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh, double dRc, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nCurrentNum = nToolNum ; m_nType = UNDEF ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; // Verifica dimensioni globali if ( dH < EPS_SMALL || dW < EPS_SMALL || dTh < EPS_SMALL) return false ; m_dHeight = dH ; m_dMrtChsWidth = dW ; m_dMrtChsThickness = dTh ; m_dRCorner = Clamp( dRc, 0., dW / 2) ; // Imposto il tipo m_nType = MORTISER ; return true ; } //---------------------------------------------------------------------------- bool Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nCurrentNum = nToolNum ; m_nType = UNDEF ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; // Verifica dimensioni globali if ( dH < EPS_SMALL || dW < EPS_SMALL || dTh < EPS_SMALL) return false ; m_dHeight = dH ; m_dMrtChsWidth = dW ; m_dMrtChsThickness = dTh ; // Imposto il tipo m_nType = CHISEL ; return true ; } //---------------------------------------------------------------------------- bool Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) { // Impostazioni generali m_sName = sToolName ; m_nCurrentNum = nToolNum ; m_nType = UNDEF ; m_Outline.Clear() ; m_ArcLineApprox.Clear() ; // Verifica sulle dimensioni if ( dH < 10 * EPS_SMALL || dR < 10 * EPS_SMALL || dRc < - EPS_SMALL || dR < dRc - EPS_SMALL) return false ; // Assegnazione dati geometrici principali m_dHeight = dH ; m_dRadius = dR ; m_dRCorner = min( dRc, dR) ; if ( m_dRCorner < 10 * EPS_SMALL) m_dRCorner = 0 ; m_dTipHeight = 0 ; m_dTipRadius = 0 ; m_dRefRadius = 0 ; m_dCutterHeight = dH ; // Utensile cilindrico con eventuale raggio corner (al limite sferico) if ( m_dRCorner <= m_dHeight / 2) { // Se Cilindrico if ( m_dRCorner < EPS_SMALL) { // inizio m_Outline.AddPoint( Point3d( 0, 0, 0)) ; // segmento orizzontale in alto m_Outline.AddLine( Point3d( m_dRadius, 0, 0)) ; m_Outline.SetCurveTempProp( 0, 1, 1) ; // segmento verticale m_Outline.AddLine( Point3d( m_dRadius, -m_dHeight, 0)) ; m_Outline.SetCurveTempProp( 1, 1, 1) ; // segmento orizzontale in basso m_Outline.AddLine( Point3d( 0, -m_dHeight, 0)) ; m_Outline.SetCurveTempProp( 2, 1, 1) ; } // Generico else { // inizio m_Outline.AddPoint( Point3d( 0, 0, 0)) ; int nInd = -1 ; // eventuale segmento orizzontale in alto if ( m_Outline.AddLine( Point3d( m_dRadius - m_dRCorner, 0, 0))) m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ; // raggio corner in alto CurveArc cvArc ; cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, -m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, 0, 0), Point3d( m_dRadius, -m_dRCorner, 0)) ; m_Outline.AddCurve( cvArc, true, 2 * EPS_SMALL) ; m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ; // eventuale segmento verticale if ( m_Outline.AddLine( Point3d( m_dRadius, -m_dHeight + m_dRCorner, 0))) m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ; // raggio corner in basso cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, -m_dHeight + m_dRCorner, 0), Point3d( m_dRadius, -m_dHeight + m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, -m_dHeight, 0)) ; m_Outline.AddCurve( cvArc, true, 2 * EPS_SMALL) ; m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ; // eventuale segmento orizzontale in basso if ( m_Outline.AddLine( Point3d( 0, -m_dHeight, 0))) m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ; } m_Outline.SetTempProp( 1, 1) ; if ( ! SetGenTool( sToolName, &m_Outline, nToolNum)) return false ; } // Utensile sfiancato else { double dCenX = m_dRadius - m_dRCorner ; double dCylRad = dCenX + sqrt( m_dRCorner * m_dRCorner - m_dHeight * m_dHeight / 4) ; // Utensile mal definito if ( dCylRad < EPS_SMALL) return false ; // Profilo m_Outline.AddPoint( Point3d( 0, 0, 0)) ; m_Outline.AddLine( Point3d( dCylRad, 0, 0)) ; m_Outline.SetCurveTempProp( 0, 1, 1) ; CurveArc cvArc ; cvArc.SetC2P( Point3d( dCenX, - 0.5 * m_dHeight, 0), Point3d( dCylRad, 0, 0), Point3d( dCylRad, - m_dHeight, 0)) ; m_Outline.AddCurve( cvArc) ; m_Outline.SetCurveTempProp( 1, 1, 1) ; m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ; m_Outline.SetCurveTempProp( 2, 1, 1) ; m_Outline.SetTempProp( 1, 1) ; if ( ! SetGenTool( sToolName, &m_Outline, nToolNum)) return false ; } m_nType = ADDITIVE ; return true ; }