/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Tolerance.h" #include "mg/Bisection.h" #include "topo/Edge.h" #include "topo/Face.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /////////////////////////////////////////////////// //MGEdge::compute_continuity////////////////////// class MG2CrvBisect:public MGBisection{ public: MG2CrvBisect( const MGCurve& curve1, const MGCurve& curve2 ); //evaluate the target value to find the solution. virtual double eval( double t1, //parameter value of m_curve1. double t2 //parameter value of m_curve2. )const=0; //This is used in compare_replace() when new_value is evaluated. necessary_to_replace() //decides if the new value is more suitable solution than the old one. //When this returns true, it means the new value is more suitable solution. virtual bool necessary_to_replace(double new_value)const{return new_value>m_value;}; //Prepare for the function compare_replace() by setting the initial value. virtual void set_initial_t(double t); //compare with the previous function value(the initial value is set //by set_initial_t) and replace t with the previous one if necessary. //The function's return value is the new parameter value. virtual double compare_replace( double t, //parameter value to compare at of m_curve1. bool& replaced //true will be returned if the t is the new solution candidate value. ); //get the result of the solution. void get_result(double& curve1_t, double& curve2_t, double& value)const{ curve1_t=m_curve1_t; curve2_t=m_curve2_t; value=m_value; } const MGCurve& m_curve1; double m_curve1_t;//first curve's parameter of m_value. const MGCurve& m_curve2; double m_curve2_t;//second curve's parameter of m_value. double m_value; }; MG2CrvBisect::MG2CrvBisect( const MGCurve& curve1, const MGCurve& curve2 ):MGBisection(curve1.param_s(),curve1.param_e()), m_value(-1.),m_curve1(curve1), m_curve2(curve2){;} //Prepare for the function compare_replace() by setting the initial value. void MG2CrvBisect::set_initial_t(double t){ m_curve1_t=t; MGPosition P1=m_curve1.eval(m_curve1_t); m_curve2_t=m_curve2.closest(P1); m_value=eval(m_curve1_t, m_curve2_t); } //compare with the previous function value(the initial value is set //by set_initial_t) and replace t with the previous one if necessary. //The function's return value is the new parameter value. double MG2CrvBisect::compare_replace( double t, //parameter value to compare at of m_curve1. bool& replaced //true will be returned if the t is the new solution candidate value. ){ MGPosition P1=m_curve1.eval(t); double t2=m_curve2.closest(P1); double value=eval(t,t2); replaced=necessary_to_replace(value); if(replaced){ m_value=value; m_curve1_t=t; m_curve2_t=t2; } return m_curve1_t; } class MGEdgeMaxDistance:public MG2CrvBisect{ public: MGEdgeMaxDistance( const MGCurve& curve1, const MGCurve& curve2 ); //evaluate the distance of curve1 and 2. double eval( double t1, //parameter value of m_curve1. double t2 //parameter value of m_curve2. )const; }; MGEdgeMaxDistance::MGEdgeMaxDistance( const MGCurve& curve1, const MGCurve& curve2 ):MG2CrvBisect(curve1,curve2){;} //evaluate the distance of curve1 and 2. double MGEdgeMaxDistance::eval( double t1, //parameter value of m_curve1. double t2 //parameter value of m_curve2. )const{ MGPosition P1=m_curve1.eval(t1); MGPosition P2=m_curve2.eval(t2); return P1.distance(P2); } class MGEdgeMinDistance:public MGEdgeMaxDistance{ public: MGEdgeMinDistance( const MGCurve& curve1, const MGCurve& curve2 ):MGEdgeMaxDistance(curve1,curve2){;}; //This is used in compare_replace() when new_value is evaluated. necessary_to_replace() //decides if the new value is more suitable solution than the old one. //When this returns true, it means the new value is more suitable solution. virtual bool necessary_to_replace(double new_distance)const{return new_distanceDs0tS){ tspan=MGInterval(tS,t1); sspan=MGInterval(s0,(s1Ds1tE){ tspan=MGInterval(t1,tE); sspan=MGInterval(s1,(s0>s1 ? s0:sE)); }else{ sspan=MGInterval(sS,s0); tspan=MGInterval((t0>t1 ? t1:tS),t0); } } } //Compute the continuities between this edge(edge1) and the edge2. //This edge and edge2 must be parameter edges of each face. //In distance, tangent, and normal, the following output will be set: //distance[0-6] as: // [0] edge1's binder edge's curve parameter that has the maximum distance with edge2. // [1] edge2's binder edge's curve parameter that has the maximum distance with edge1. // [2] the evaluated maximum distance between edge1 and edge2 at distance[0] and [1] // [3] edge1's binder edge's curve parameter that has the minimum distance with edge2. // [4] edge2's binder edge's curve parameter that has the minimum distance with edge1. // [5] the evaluated minimum distance between edge1 and edge2 at distance[3] and [4] // [6] mean distance between edge1 and edge2. //tangent[0-3] as: // [0] edge1's binder edge's curve parameter that has the maximum tangent difference with edge2. // [1] edge2's binder edge's curve parameter that has the maximum tangent difference with edge1. // [2] the evaluated maximum tangent difference between edge1 and edge2 at tangent[0] and [1]. // [3] mean tangent difference between edge1 and edge2. //normal[0-3] as: // [0] edge1's binder edge's curve parameter that has the maximum normal difference with edge2. // [1] edge2's binder edge's curve parameter that has the maximum normal difference with edge1. // [2] the evaluated maximum normal difference between edge1 and edge2 at normal[0] and [1]. // [3] mean normal difference between edge1 and edge2. void MGEdge::compute_continuity( const MGEdge& edge2, //Parameter edges of the 2nd face. double distance[7], double tangent[4], double normal[4] )const{ MGEdge* be1=make_binder_with_curve(); std::unique_ptr crv1(be1->curve_limitted());//world curve repr of edge1. MGEdge* be2=edge2.make_binder_with_curve(); std::unique_ptr crv2(be2->curve_limitted());//world curve repr of edge1. MGInterval sspan, tspan; get_comparison_span(*crv1,*crv2,sspan,tspan); int nspoint=crv1->offset_div_num(sspan); int ntpoint=crv2->offset_div_num(tspan); if(nspoint>ntpoint){ compute_continuity2(sspan,nspoint,edge2,distance,tangent,normal); }else{ edge2.compute_continuity2(tspan,ntpoint,*this,distance,tangent,normal); double tmp=distance[0];distance[0]=distance[1]; distance[1]=tmp; tmp=distance[3];distance[3]=distance[4]; distance[4]=tmp; tmp=tangent[0];tangent[0]=tangent[1]; tangent[1]=tmp; tmp=normal[0];normal[0]=normal[1]; normal[1]=tmp; } } //Compute continuity, given the evaluation interval and the division number. //This is a parameter edge that has the star face. void MGEdge::compute_continuity2( const MGInterval& span,//this edge's binder edge's parameter span. int npoint, //division number of this edge's binder curve interval sspan. const MGEdge& edge2, //the second parameter edge that has the star face. double distance[7], //evaluated data will be set in distance, tangent, and normal. double tangent[4], //See compute_continuity double normal[4] )const{ MGEdge* be1=binder_edge(); std::unique_ptr crv1(be1->curve_limitted());//world curve repr of edge1. MGEdge* be2=edge2.binder_edge(); std::unique_ptr crv2(be2->curve_limitted());//world curve repr of edge1. //Here, sx means crv1's parameter value, and tx means crv2's. double s_maxd=0., s_mind=0., max_distance=-1., min_distance=-1., mean_distance=0; double s_tdif=0., max_tdif=-1., mean_tdif=0.; double s_ndif=0., max_ndif=-1., mean_ndif=0.; int nspan=npoint-1; double rzero2=MGTolerance::rc_zero()*2.; MGEdgeMaxDistance max_dist(*crv1,*crv2); MGEdgeMinDistance min_dist(*crv1,*crv2); MGEdgeTanDifference max_tdiff(*crv1,*crv2); MGEdgeNormalDifference max_ndiff(*this,*crv1,edge2,*crv2); //Find the extreme points in the npoint discrete points. double s=span.low_point(), sdelta=span.length().value()/nspan; if(sdelta<=crv1->param_span()*rzero2){ max_dist.set_initial_t(s); min_dist.set_initial_t(s); max_tdiff.set_initial_t(s); max_ndiff.set_initial_t(s); max_dist.get_result(distance[0],distance[1],distance[2]); min_dist.get_result(distance[3],distance[4],distance[5]); distance[6]=distance[2]; max_tdiff.get_result(tangent[0],tangent[1],tangent[2]); tangent[3]=tangent[2]; max_ndiff.get_result(normal[0],normal[1],normal[2]); normal[3]=normal[2]; return; } for(int i=0; ieval(s); double t=crv2->closest(P1); //max distance info. double disti=max_dist.eval(s,t); mean_distance+=disti; if(max_distancedisti){ s_mind=s; min_distance=disti; } //max tdif(tangent difference) info. double Tanglei=max_tdiff.eval(s,t); mean_tdif+=Tanglei; if(max_tdif