/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Tolerance.h" #include "mg/EReal.h" #include "mg/LBRep.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // MGTolerance.cc // Implementation of MGTolerance. // MGTolerance::MGTolerance() : // メンバデータの初期化 // 等しいとみなす2点間の距離-----Machine Zero Version m_mach_zero(1.0E-20), // 等しいとみなす2点間の距離-----Absolute Version m_wc_zero(0.5E-3), // m_wc_zero の2乗-----Absolute Version m_wc_zero_sqr(m_wc_zero*m_wc_zero), // 等しいとみなす2点間の距離-----Relative Version m_rc_zero(1.0E-6), // m_rc_zero の2乗-----Relative Version m_rc_zero_sqr(m_rc_zero*m_rc_zero), // 2つが等しいとみなす角度(in radina). m_angle_zero(.0025), // 2曲線が等しいとみなすトレランス m_line_zero(m_wc_zero), // 隣り合うKnotの比の最大値 m_max_knot_ratio(5.0E+2), // スタックカウンタ m_count(0){ std::fill_n(m_mach_zero_stack, MG_MAX_TOL_STACK_SIZE, 0.);//m_mach_zero std::fill_n(m_wc_zero_stack, MG_MAX_TOL_STACK_SIZE, 0.);// m_wc_zero std::fill_n(m_rc_zero_stack, MG_MAX_TOL_STACK_SIZE, 0.);// m_rc_zero std::fill_n(m_angle_zero_stack, MG_MAX_TOL_STACK_SIZE, 0.);// m_angle_zero std::fill_n(m_line_zero_stack, MG_MAX_TOL_STACK_SIZE, 0.);// m_line_zero std::fill_n(m_max_knot_ratio_stack, MG_MAX_TOL_STACK_SIZE, 0.); push(); assert(m_count == 1); } MGTolerance::~MGTolerance(){ pop(); } // // メンバ関数 // MGTolerance& MGTolerance::instance(){ static MGTolerance theInst; return theInst; } // 更新 // m_mach_zeroを変更する。 double MGTolerance::set_mach_zero(double mach_zero){ MGTolerance& t = instance(); double save=t.m_mach_zero; t.m_mach_zero = mach_zero; if(mach_zero<=0.0) t.m_mach_zero=1.0E-20; return save; } // m_wc_zeroを変更する。 double MGTolerance::set_wc_zero(double wc_zero){ MGTolerance& t = instance(); double save=t.m_wc_zero; t.m_wc_zero = wc_zero; if(t.m_wc_zero0 );//*****Stack underflow****** if( t.m_count > 0 ){ int id=t.m_count-1; t.m_mach_zero = t.m_mach_zero_stack[ id ]; t.m_wc_zero = t.m_wc_zero_stack[ id ]; t.m_wc_zero_sqr = t.m_wc_zero * t.m_wc_zero; t.m_rc_zero = t.m_rc_zero_stack[ id ]; t.m_rc_zero_sqr = t.m_rc_zero * t.m_rc_zero; t.m_angle_zero = t.m_angle_zero_stack[ id ]; t.m_line_zero = t.m_line_zero_stack[ id ]; t.m_max_knot_ratio = t.m_max_knot_ratio_stack[ id ]; t.m_count = id; } } // Global Functions // トレランスを考慮して与えられた値が0か調べる-----Machine Zero Version. bool MGMZero(double data) { return (fabs(data) <= MGTolerance::mach_zero()); } // トレランスを考慮して与えられた2つの double が一致するか調べる。 // 等しい時 true(non zero) を返却する-----Absolute Version. bool MGAEqual (double data1, double data2) { return fabs(data1-data2) <= MGTolerance::wc_zero(); } // トレランスを考慮して与えられた値が0か調べる-----Absolute Version. bool MGAZero(double data) { return (fabs(data) <= MGTolerance::wc_zero()); } //Test if difference of two data is less than MGTolerance::rc_zero() //after changing data1 and data2 proportionally for data1 or 2 to be 1. bool MGREqual2(double data1, double data2) { return MGREqual(data1,data2); } //Test if difference of two data is less than MGTolerance::rc_zero() //after changing data1 and data2 proportionally for data1 or 2 to be 1. bool MGREqual(double data1, double data2){ double d2e=data2*MGTolerance::rc_zero(); if(d2e<0.) d2e=-d2e; double d2md1=data2-data1; if(d2md1>d2e) return 0; if(d2md1<-d2e) return 0; return 1; } //Test if difference of two data is equal. //Comparison is: //test if abs(data1-data2)/base_length is less than MGTolerance::rc_zero(). bool MGREqual_base(double data1, double data2, double base_length){ return MGRZero2(data1-data2,base_length); } bool MGREqual_base(MGEReal data1, MGEReal data2, const MGEReal& base_length){ if(data1.finite() && data2.finite()){ double dif=data1.value()-data2.value(); if(base_length.finite()) return MGRZero2(dif,base_length.value()); if(dif>=0.) return dif<=MGTolerance::wc_zero(); return (-dif)<= MGTolerance::wc_zero(); } if(data1.minus_infinite() && data2.minus_infinite()) return true; if(data1.plus_infinite() && data2.plus_infinite()) return true; return false; } // トレランスを考慮して与えられた値が0か調べる1-----Relative Version. bool MGRZero(double data) { return (fabs(data) <= MGTolerance::rc_zero()); } //トレランスを考慮して与えられた値が0か調べる2-----Relative Version //Test if data is less or equal to rc_zero() compared to base_length. //Comparison is done after data and base_length are so changed //that base_length is 1. //If base_length is zero, MGRZero2 returns always false. bool MGRZero2(double data, double base_length){ double e=base_length*MGTolerance::rc_zero(); if(e<0.) e=-e; if(data<-e) return 0; if(data>e) return 0; return 1; } bool MGRZero2(double data, const MGEReal& base_length){ if(base_length.finite()) return MGRZero2(data,base_length.value()); if(data>=0.) return data<=MGTolerance::wc_zero(); return (-data)<= MGTolerance::wc_zero(); } // トレランスを考慮して与えられた角度(Radian)が直角(π/2)か調べる。 bool MGRight_angle(double cos_data) { return (fabs(cos_data) <= MGTolerance::angle_zero()); } // トレランスを考慮して与えられた角度(Radian)が0か調べる。 bool MGZero_angle (double data){ return (fabs(data) <= MGTolerance::angle_zero()); } // Compute radian angle from cosine and sine value. //Function's return value is angle in radian, from zero to 2PAI. double MGAngle(double ca //Cosine value , double sa) { //Sine value double ang; if(ca>=0. && sa>=0.){ // 0<= angle <=HALFPAI. if(ca>=sa) ang=asin(sa); else ang=acos(ca); }else if(ca<=0. && sa>=0.){ // HALFPAI<= angle <=PAI. if(sa>=-ca) ang=acos(ca); else ang=mgPAI-asin(sa); }else if(ca<=0. && sa<=0.){ // PAI<= angle <=3*PAI/2.. if(sa>=ca) ang=mgPAI-asin(sa); else ang=mgPAI*2.-acos(ca); }else{ // 3*PAI/2.<= angle <=DBLPAI. if(ca<=-sa) ang=mgPAI*2.-acos(ca); else ang=mgPAI*2.+asin(sa); } return ang; } void MGPrintBSpline(int k, int n, const double* t, const double* rcoef, int irc, int ncd){ MGBPointSeq rc(n,ncd); MGKnotVector kntv(k,n,t); for(int i=0; i