/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Pvector.h" #include "mg/Tolerance.h" #include "mg/Box.h" #include "mg/KnotArray.h" #include "mg/SPointSeq.h" #include "mg/Straight.h" #include "mg/CCisect_list.h" #include "mg/LBRepEndC.h" #include "mg/SBRepEndC.h" #include "mg/SBRepTP.h" #include "mg/Coons.h" #include "mg/SBRep.h" #include "cskernel/Bvstan.h" using namespace std; #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //using namespace std; //Compute 2nd derivative. MGVector get_2nd(const MGVector& first,const MGVector& second_guess,double curvature){ if(MGRZero(second_guess.len())) return second_guess; MGUnit_vector e2(second_guess); double len=first.len()*curvature; return e2*len; } //ノットをあわせた後の境界線、ブレンド関数、データポイントから点列を求める。 void bilinear_spoint_proc( const MGPvector& brepl,//ノットベクトルをあわせた後の境界線 const MGCurve& blendCrvU, //空間次元1のu方向のブレンド曲線(パラメータ、値域ともに0,1) const MGCurve& blendCrvV, //空間次元1のv方向のブレンド曲線(パラメータ、値域ともに0,1) const MGNDDArray& utau, //u方向のデータポイント const MGNDDArray& vtau, //v方向のデータポイント MGSPointSeq& spoint) //点列 { spoint = MGSPointSeq(utau.length(), vtau.length(), brepl[0]->sdim()); //4隅の点は境界線の端点の中間とする MGPosition p00 = (brepl[0]->start_point() + brepl[3]->start_point()) / 2.0, p01 = (brepl[2]->start_point() + brepl[3]->end_point()) / 2.0, p10 = (brepl[0]->end_point() + brepl[1]->start_point()) / 2.0, p11 = (brepl[1]->end_point() + brepl[2]->end_point()) / 2.0; //境界線上の点を求める int i, nu=utau.length(), nv=vtau.length(); int num1=nu-1, nvm1=nv-1; for(i=0; ieval(utau(i))); spoint.store_at(i, nvm1, brepl[2]->eval(utau(i))); } for(i=0; ieval(vtau(i))); spoint.store_at(num1, i, brepl[1]->eval(vtau(i))); } //内部点を求める double spanu = brepl[0]->param_span(), spanv = brepl[1]->param_span(); for(i=1; i& perimeters, const MGSBRepTP& tp, //接続面(パラメータ範囲は境界線と同じ) MGSPointSeq& spoint, //点列 MGNDDArray& utau, //u方向のデータポイント MGNDDArray& vtau //v方向のデータポイント ){ //端末ベクトル、データポイントを求める。 MGENDCOND condk[4]={MGENDC_NO,MGENDC_NO,MGENDC_NO,MGENDC_NO}; for(int i=0; i<4; i++) if(tp.specified(i)) condk[i] = MGENDC_1D; //点列を求める MGKnotVector& knotu = perimeters[0]->knot_vector(); MGKnotVector& knotv = perimeters[1]->knot_vector(); utau = MGNDDArray(condk[3], condk[1], knotu);//std::cout<<"utau="<& perimeters ){ //境界線がC1連続か、接続面のパラメータ範囲が境界線と同じかどうか調べる for(int i=0; i<4; i++){ //if(!edge_crvl[i]->cn_continuity(1)) return -1; //C1連続性のチェック if(!tp.specified(i)) continue; MGLBRep& tpi=tp.TP(i); const MGInterval cirange=edge_crvl[i]->param_range(); if(cirange != tpi.param_range()) tpi.change_range(cirange.low_point(),cirange.high_point()); } //Make the tolerances smaller. double lzero=MGTolerance::line_zero();//save line zero; MGTolerance::set_line_zero(lzero*.3); double azero=MGTolerance::angle_zero();//save line zero; MGTolerance::set_angle_zero(azero*.3); //リビルドを行う int k=4; //オーダーは4とする std::vector temp_crvl(2); perimeters.resize(4); temp_crvl[0] = edge_crvl[0]; temp_crvl[1] = edge_crvl[2]; MGLBRep* tplb[2]={0,0}; if(tp.specified(0)) tplb[0]=&(tp.TP(0)); if(tp.specified(2)) tplb[1]=&(tp.TP(2)); MGPvector temp_brepl = rebuild_knot(temp_crvl, k, tplb); //if(!temp_brepl.size()){ // MGTolerance::set_line_zero(lzero);return -3; //} tp.set_TP(0,std::unique_ptr(tplb[0])); tp.set_TP(2,std::unique_ptr(tplb[1])); perimeters.reset(0, temp_brepl.release(0)); perimeters.reset(2, temp_brepl.release(1)); temp_crvl[0] = edge_crvl[1]; temp_crvl[1] = edge_crvl[3]; tplb[0]=tplb[1]=0; if(tp.specified(1)) tplb[0]=&(tp.TP(1)); if(tp.specified(3)) tplb[1]=&(tp.TP(3)); MGPvector temp_brepl2 = rebuild_knot(temp_crvl, k, tplb); //if(!temp_brepl2.size()){ // MGTolerance::set_line_zero(lzero);return -3; //} tp.set_TP(1,std::unique_ptr(tplb[0])); tp.set_TP(3,std::unique_ptr(tplb[1])); perimeters.reset(1, temp_brepl2.release(0)); perimeters.reset(3, temp_brepl2.release(1)); //Restore the original tolerance. MGTolerance::set_line_zero(lzero); MGTolerance::set_angle_zero(azero); MGLBRep& l0=*(perimeters[0]); MGLBRep& l1=*(perimeters[1]); MGLBRep& l2=*(perimeters[2]); MGLBRep& l3=*(perimeters[3]); //make the knots fine. MGKnotVector tu(l0.knot_vector()), tv(l1.knot_vector()); tu.change_knot_number(tu.bdim()*3); tv.change_knot_number(tv.bdim()*3); MGCurve* crv2[4]; for(int i=0; i<4; i++) crv2[i]=edge_crvl[i]->clone(); double u0=tu.param_s(), u1=tu.param_e(); double v0=tv.param_s(), v1=tv.param_e(); crv2[0]->change_range(u0,u1); crv2[1]->change_range(v0,v1); crv2[2]->change_range(u0,u1); crv2[3]->change_range(v0,v1); l0=MGLBRep(*(crv2[0]),tu); l1=MGLBRep(*(crv2[1]),tv); l2=MGLBRep(*(crv2[2]),tu); l3=MGLBRep(*(crv2[3]),tv); for(int i=0; i<4; i++){ delete crv2[i]; if(!tp.specified(i)) continue; MGKnotVector* t=&tu; if(i%2) t=&tv; MGLBRep& tpi=tp.TP(i); tpi=MGLBRep(tpi,*t); } //Adjust the corner points. MGPosition P0=(l0.start_point()+l3.start_point())*.5; MGPosition P1=(l0.end_point()+l1.start_point())*.5; MGPosition P2=(l1.end_point()+l2.end_point())*.5; MGPosition P3=(l3.end_point()+l2.start_point())*.5; double fixp[2]; //P0 fixp[0]=l0.param_e(); l0.move(2,l0.param_s(),P0,fixp); fixp[0]=l3.param_e(); l3.move(2,l3.param_s(),P0,fixp); //P1 fixp[0]=l0.param_s(); l0.move(2,l0.param_e(),P1,fixp); fixp[0]=l1.param_e(); l1.move(2,l1.param_s(),P1,fixp); //P2 fixp[0]=l1.param_s(); l1.move(2,l1.param_e(),P2,fixp); fixp[0]=l2.param_s(); l2.move(2,l2.param_e(),P2,fixp); //P3 fixp[0]=l2.param_e(); l2.move(2,l2.param_s(),P3,fixp); fixp[0]=l3.param_s(); l3.move(2,l3.param_e(),P3,fixp); } void rebuild_curve( MGPvector& edges, MGSBRepTP& tp, //接続面(パラメータ範囲は境界線と同じ) MGPvector& perimeters ){ const MGCurve* edge_crvl[4]; for(int i=0; i<4; i++) edge_crvl[i]=edges[i]; rebuild_curve(edge_crvl,tp,perimeters); } //4本の境界線、ブレンド関数、接続面を与えて面を生成する。 //境界線はvmin,umax,vmax,uminの順で、vmin,vmaxの向きをuminからumaxの方向に //umin,umaxの向きをvminからvmaxの方向になっているものとする。境界線のノットベクトル //をあわせるときの誤差はline_zero()を使用している。ブレンド曲線はパラメータ範囲0,1 //で値域も0,1である。接続面(MGSBRepTP)のパラメータ範囲は各境界線と同じとする。 // エラーコード: // 0: 正常終了 // -1: 境界線がC1連続でなかった // -2: 接続面のパラメータ範囲が境界線と違った // -3: 境界線のノットベクトルをあわせられなかった // -4: 接続面のパラメータ範囲を変更できなかった // -5: 点列が求まらなかった // -6: 端末条件が求まらなかった // -7: 面が生成できなかった MGSBRep::MGSBRep( const MGCurve* edge_crvl[4], //境界線リスト(vmin,umax,vmax,uminの順,辺番号0,1,2,3の順) const MGCurve& blendCrvU, //空間次元1のu方向のブレンド曲線(パラメータ、値域ともに0,1) const MGCurve& blendCrvV, //空間次元1のv方向のブレンド曲線(パラメータ、値域ともに0,1) const MGSBRepTP& tp, //接続面(パラメータ範囲は境界線と同じ) int& error):MGSurface() //エラーコード { //点列、ノットベクトル、データポイントを求める //for(int iii=0;iii<4; iii++) std::cout<<(*edge_crvl[iii]); MGSBRepTP tempTP(tp); MGSPointSeq spoint; MGNDDArray utau, vtau; MGPvector perimeters; //1. Adjust parameter range of the tp and edge_crvl. rebuild_curve(edge_crvl,tempTP,perimeters); //2. Build spoint data. bilinear_spoint(blendCrvU,blendCrvV,perimeters,tempTP,spoint,utau,vtau); //3. 接続条件(MGSBRepEndC)を求める MGSBRepEndC endc; if(!bilinear_endc(spoint, tempTP,perimeters, blendCrvU, blendCrvV, utau, vtau, endc)){ error = -6; return; } //4. 点列、データポイント、ノットベクトル、接続条件より面を生成する MGKnotVector& knotu=perimeters[0]->knot_vector(); MGKnotVector& knotv=perimeters[1]->knot_vector(); //std::cout<& edges, //境界線リスト(vmin,umax,vmax,uminの順,辺番号0,1,2,3の順) int& error , //エラーコードが出力される const MGCurve* blendCrvU,//空間次元1のu方向のブレンド曲線(パラメータ、値域ともに0,1) const MGCurve* blendCrvV //空間次元1のv方向のブレンド曲線(パラメータ、値域ともに0,1) ){ MGPosition zero(1); zero(0)=0.; MGPosition one(1); one(0)=1.; MGStraight zero_one(one,zero); const MGCurve* blendu; const MGCurve* blendv; if(blendCrvU) blendu=blendCrvU; else blendu=&zero_one; if(blendCrvV) blendv=blendCrvV; else blendv=&zero_one; MGSBRepTP tp; MGSPointSeq spoint; MGNDDArray utau, vtau; MGPvector perimeters; //1. Adjust parameter range of the edge_crvl. rebuild_curve(edges,tp,perimeters); //2. Build spoint data. bilinear_spoint(*blendu,*blendv,perimeters,tp,spoint,utau,vtau); //3. 点列、データポイント、ノットベクトル、接続条件より面を生成する MGKnotVector& knotu=perimeters[0]->knot_vector(); MGKnotVector& knotv=perimeters[1]->knot_vector(); //std::cout<1. curvature will be made small. //If alpha=null, all of the coefs are assumed to be 1. ):MGSurface(){ // std::cout<<*(edge_crvl[0])< perimeters; rebuild_curve(edge_crvl,tp2,perimeters); //std::cout<knot_vector(); double u0=tu.param_s(), u1=tu.param_e(); MGKnotVector& tv=perimeters[1]->knot_vector(); double v0=tv.param_s(), v1=tv.param_e(); //Change parameter range to (0., 1.). int i; for(i=0; i<4; i++){ perimeters[i]->change_range(0., 1.); if(tp2.specified(i)) tp2.TP(i).change_range(0., 1.); } //std::cout< derivatives(4); bool along_u=true; //Method 1. MGSBRep ruled0(along_u,perimeters);//std::cout<