/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Bisection.h" #include "mg/Box.h" #include "mg/Knot.h" #include "mg/Unit_vector.h" #include "mg/CParam_list.h" #include "mg/Position_list.h" #include "mg/Straight.h" #include "mg/LBRep.h" #include "mg/TrimmedCurve.h" #include "mg/CompositeCurve.h" #include "mg/CSisect_list.h" #include "mg/SSisect_list.h" #include "mg/SurfCurve.h" #include "mg/FSurface.h" #include "mg/Plane.h" #include "mg/SBRep.h" #include "mg/RSBRep.h" #include "mg/Pvector.h" #include "mg/Tolerance.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif using namespace std; // Implementation of MGFSurface projection. //曲線を面に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、 ///vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///get perpendicular or vector projection curve list. ///uv projection curves are put into vec_crv_uv(rc_zero() is used), ///3d projection curves are put into vec_crv(line_zero() is used) respectively. //戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not NULL, ///and normal to the surface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the surfaces(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then /// (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGCurve::project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ return surf.projectbyApproximateAsLBRep(*this,vec_crv_uv,vec_crv,vec); //This is default process of a curve. } ///曲線を面に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、 ///vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///get perpendicular or vector projection curve list. ///uv projection curves are put into vec_crv_uv(rc_zero() is used), ///3d projection curves are put into vec_crv(line_zero() is used) respectively. ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not NULL, ///and normal to the surface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the surfaces(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then /// (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGStraight::project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ const MGPlane* plane=dynamic_cast(&surf); if(plane){ return plane->project(*this,vec_crv_uv,vec_crv,vec); } if(!vec.is_null()) //ベクトル投影 return surf.projVector(*this, vec_crv_uv, vec_crv, vec); else return surf.projNormal(*this, vec_crv_uv, vec_crv); } ///曲線を面に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、 ///vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///get perpendicular or vector projection curve list. ///uv projection curves are put into vec_crv_uv(rc_zero() is used), ///3d projection curves are put into vec_crv(line_zero() is used) respectively. ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not NULL, ///and normal to the surface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the surfaces(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then /// (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGLBRep::project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ if(order()==2){ const MGPlane* plane=dynamic_cast(&surf); if(plane) return project(*plane,vec_crv_uv,vec_crv,vec); } return surf.projectbyRemovKnots(*this,vec_crv_uv,vec_crv,vec); } int MGLBRep::project( const MGPlane& plane, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ if(order()==2){ const MGKnotVector& t=knot_vector(); int n=t.bdim(); MGPosition Pi=eval(t(1)); MGPvector vec_crv_uv2; /// vec_crv2; ///<3d projection curve. for(int i=1; i(vec_crv_uv.back()); lbiuv->connect(0,2,MGLBRep(*(vec_crv_uv2.back()),0,1)); MGLBRep* lbi=static_cast(vec_crv.back()); lbi->connect(0,2,MGLBRep(*(vec_crv2.back()),0,1)); //std::cout<<(*lbiuv)<=0: number of curves obtained, <0 : Some error detected. int MGCompositeCurve::project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ project_onto_surface(surf,vec_crv_uv,vec_crv,vec); return (int)vec_crv.size(); } ///曲線を面に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、 ///vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///get perpendicular or vector projection curve list. ///uv projection curves are put into vec_crv_uv(rc_zero() is used), ///3d projection curves are put into vec_crv(line_zero() is used) respectively. ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not NULL, ///and normal to the surface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the surfaces(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then /// (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGSurfCurve::project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ if(base_surface()==&surf){ MGLBRep* lbuv=new MGLBRep; m_curve.approximate_as_LBRep(*lbuv); vec_crv_uv.push_back(lbuv); MGLBRep* lbxyz=new MGLBRep; approximate_as_LBRep(*lbxyz); vec_crv.push_back(lbxyz); }else{ surf.projectbyApproximateAsLBRep(*this,vec_crv_uv,vec_crv,vec); } return (int)vec_crv.size(); } ///曲線を面に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、 ///vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///get perpendicular or vector projection curve list. ///uv projection curves are put into vec_crv_uv(rc_zero() is used), ///3d projection curves are put into vec_crv(line_zero() is used) respectively. ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not NULL, ///and normal to the surface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the surfaces(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then /// (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGTrimmedCurve::project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ if(is_same_range()) return m_curve->project(surf,vec_crv_uv,vec_crv,vec); return surf.projectbyApproximateAsLBRep(*this,vec_crv_uv,vec_crv,vec); } ///与えられた曲線を自身に面直またはベクトル投影して曲線リストを求める。引数vecが与えられないとき、面直投影する。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///Obtain the projected curve of a curve onto the FSurface. ///The direction of the projection is along the vector vec if the vec is not ///NULL, and normal to the FSurface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the FSurface(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then ///(vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGFSurface::project( const MGCurve& crv, MGPvector& vec_crv_uv, //Projected curve(surface parameter (u,v) representation) will be appended. MGPvector& vec_crv, //Projected curve(world coordinate(x,y,z) representation) will be appended. const MGVector& vec )const{ //Invoke each curve project process. return crv.project(*this,vec_crv_uv,vec_crv,vec); } ///与えられた曲線を自身に面直またはベクトル投影して曲線リストを求める。引数vecが与えられないとき、面直投影する。 ///投影曲線は3次元曲線としてvec_crvに格納される。 ///uv曲線のトレランスはline_zero()を使用している。 ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///Obtain the projected curve of a curve onto the FSurface. ///The direction of the projection is along the vector vec if the vec is not ///NULL, and normal to the FSurface if the vec is NULL. ///Output of 'project' is general world coordinate curves('vec_crv') ///Function's return value is: /// >=0: number of curves obtained, <0 : Some error detected. int MGFSurface::project( const MGCurve& crv, //given curve. MGPvector& vec_crv, //Projected curve(world coordinate(x,y,z) representation) will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ MGPvector vec_crv_uv; return crv.project(*this,vec_crv_uv,vec_crv,vec); } ///与えられた曲線を自身に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は面上のパラメータ曲線と3次元曲線としてそれぞれ順番に、 ///vec_crv_uv, vec_crvに格納される。 ///uv曲線のトレランスはrc_zero()を、3次元曲線はline_zero()をそれぞれ使用している。 ///get perpendicular or vector projection curve list. ///uv projection curves are put into vec_crv_uv(rc_zero() is used), ///3d projection curves are put into vec_crv(line_zero() is used) respectively. ///引数: /// const MGCurve& crv, (I/ ) given curve. /// MGPvector& vec_crv_uv, ( /O) uv projection curve. /// MGPvector& vec_crv, ( /O) 3d projection curve. /// const MGVector& vec=mgNULL_VEC (I/ ) projection vector. ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not ///NULL, and normal to the surface if the vec is NULL. ///Output of 'project' is two kind of curves: ///one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of ///the parameter space of the surfaces(vec_crv_uv). ///vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then /// (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGPlane::project( const MGStraight& sl, //given curve. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ MGSTRAIGHT_TYPE kind=sl.straight_type(); if(kind==MGSTRAIGHT_EMPTY) return 0; const MGPosition P=sl.start_point(); if(vec.is_null()){ MGPosition uvP; on(P,uvP); if(kind==MGSTRAIGHT_SEGMENT){ const MGPosition Q=sl.end_point(); MGPosition uvQ; on(Q,uvQ); vec_crv_uv.push_back(new MGStraight(uvQ,uvP)); vec_crv.push_back(new MGStraight(eval(uvQ),eval(uvP))); return 1; } const MGVector& dir=sl.direction(); MGPosition uvdir; on(dir,uvdir); vec_crv_uv.push_back(new MGStraight(kind,uvdir,uvP)); vec_crv.push_back(new MGStraight(kind,eval(uvdir),eval(uvP))); }else{ MGStraight sl1(MGSTRAIGHT_UNLIMIT,vec,P); MGCSisect is1; relation(sl1,is1); const MGPosition& uvPprj=is1.param_surface(); const MGPosition& Pprj=is1.point(); if(kind==MGSTRAIGHT_SEGMENT){ const MGPosition Q=sl.end_point(); MGStraight sl2(MGSTRAIGHT_UNLIMIT,vec,Q); MGCSisect is2; relation(sl2,is2); const MGPosition& uvQprj=is2.param_surface(); const MGPosition& Qprj=is2.point(); vec_crv_uv.push_back(new MGStraight(uvQprj,uvPprj)); vec_crv.push_back(new MGStraight(Qprj,Pprj)); return 1; } const MGVector& dir=sl.direction(); MGStraight sl3(MGSTRAIGHT_UNLIMIT,vec,dir); MGCSisect is3; relation(sl3,is3); const MGPosition& uvDirprj=is3.param_surface(); const MGPosition& Dirprj=is3.point(); vec_crv_uv.push_back(new MGStraight(kind,uvDirprj,uvPprj)); vec_crv.push_back(new MGStraight(kind,Dirprj,Dirprj)); } return 1; } ///与えられた曲線を自身に面直またはベクトル投影して曲線リストを求める。 ///投影曲線は3次元曲線としてvec_crvに格納される。 ///3次元曲線のtoleranceはline_zero()を使用している。 ///get perpendicular or vector projection curve list. ///3d projection curves are put into vec_crv(line_zero() is used). ///引数: /// const MGCurve& crv, (I/ ) given curve. /// MGPvector& vec_crv, ( /O) 3d projection curve. /// const MGVector& vec=mgNULL_VEC (I/ ) projection vector. ///戻り値: /// 投影曲線の数: 投影曲線が求まった /// 0: 投影曲線が求まらなかった /// -1: 内部処理エラー /// -2: 収束処理エラー(収束しなかった) ///追記:引数vecが与えられない(null)とき、面直投影する。 ///Obtain the projected curve of a curve onto the surface. ///The direction of the projection is along the vector vec if the vec is not ///NULL, and normal to the surface if the vec is NULL. ///Output of 'project' is general world coordinate curves('vec_crv') ///Function's return value is: /// >=0: number of curves obtained, <0 : Some error detected. int MGPlane::project( const MGCurve& crv, //given curve. MGPvector& vec_crv,//3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const{ MGPvector vec_crv_uv; return crv.project(*this,vec_crv_uv,vec_crv,vec); } //トレランスに応じた細分したデータポイントを求める void prjGetDataPoints( const MGFSurface& surf, const MGCurve& curve, const MGPosition& tuv0,//parameter range of curve to get the data point, const MGPosition& tuv1,//From tuv0 to tuv1. MGNDDArray& tau //data points will be output. ){ double t0=tuv0[0], t1=tuv1[0]; MGInterval cspan(t0, t1); int n1=curve.offset_div_num(cspan); const MGSurface* srf=surf.get_surface_pointer(); MGCurve* pcrv1=srf->parameter_curve(1,(tuv0[1]+tuv1[1])*.5); MGInterval cspan2(tuv0[1], tuv1[1]); int n2=pcrv1->offset_div_num(cspan2); delete pcrv1; MGCurve* pcrv2=srf->parameter_curve(0,(tuv0[2]+tuv1[2])*.5); MGInterval cspan3(tuv0[2], tuv1[2]); int n3=pcrv2->offset_div_num(cspan3); delete pcrv2; int n=n1; if(n& ranges,//start(ranges[0]) and end(ranges[1]) point parameter //of the curve and the face. //On return ranges will be so updated that processed rages[0] to [1] //are pop_front(). MGLBRep*& crvProjected //newed object will be returend when obtained. //When not obtained, null will be returned. ){ crvProjected=0; MGPosition tuv0=ranges.front(); ranges.pop_front(); MGPosition tuv1=ranges.front(); ranges.pop_front(); MGNDDArray tau;//data point to get the projected points. //tau[0] is tuv[0][0], and tau[n-1]=tuv[1][0]. prjGetDataPoints(f,curve,tuv0,tuv1,tau); int ntau = tau.length(); int ntaum1=ntau-1; MGBPointSeq bp_add(ntau, 5); //xyz,uvをあわせたB表現[x,y,z,u,v] prj_store_bp(f,0,tuv0[1],tuv0[2],bp_add);//始点を求める const MGSurface* srf=f.get_surface_pointer(); MGPosition uv, uv_guess(tuv0[1],tuv0[2]); int i=1; for(; ion_a_perimeter(uv(0), uv(1), periNum); //辺にのっていたらそのパラメータを使用する(uvがupdateされている) uv_guess = uv; //推量点を更新する prj_store_bp(f,i,uv[0],uv[1],bp_add);//始点を求める } prj_store_bp(f,i++,tuv1[1],tuv1[2],bp_add);//End pointを求める bp_add.set_length(i); //曲線を作成してベクトルに挿入する MGBox bxAddXYZ(3,bp_add.box()); //xyzのボックスを求める //ショートアークのチェックをする if(bxAddXYZ.len() <= MGTolerance::wc_zero()) return; MGBPointSeq tmpBpXYZ(3,bp_add); MGNDDArray tauXYZ(tmpBpXYZ); crvProjected = new MGLBRep(tauXYZ, bp_add, 4, 4.); crvProjected->remove_knot(0,3); //最初の3次元(XYZ)をline_zeroでノット削除 //std::cout<<(*crvProjected); } //Normalize the parameter of the input range[.][0], i.e. if the value is alomost equalt to //a knot value, round the value into the knot value. This is usefull especially for //start or end parameter value. int normalize_check_isect( const MGCurve& curve, int retval, MGPosition range[2] ){ //パラメータ値を正規化する MGPosition& tuv0=range[0]; MGPosition& tuv1=range[1]; double ts=tuv0(0)=curve.param_normalize(tuv0[0]); double te=tuv1(0)=curve.param_normalize(tuv1[0]); if((te-ts)<=curve.param_error()){ if(retval==1) return 0; //投影範囲が誤差範囲の場合交点となるので0を返す else return -2; } return retval; } class MGPrjBisect{ public: MGPrjBisect( double ts, //parameter range from ts to te. double te ); //Virtual Destructor virtual ~MGPrjBisect(){;}; //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 void compare_replace( double t //parameter value to compare at. )=0; int solve( double tolerance//The tolerance to halt the bisection iteration. ); protected: double m_ts, m_te; //the curve's parameter range from m_ts to m_te, or from m_te to m_ts. //note that m_tsparam_error(); MGProjBoundaryParam solver(f,curve,tuv,ts,te); solver.solve(crvError); return solver.get_result(); } //A virtual super class to solve non-linear equations by bicection methos. MGPrjBisect::MGPrjBisect( double ts, //parameter range from ts to te. double te ):m_ts(ts), m_te(te){} //Compute the fn(t)'s parameter value that is the maxima //Function's return value will be the solution obtained. int MGPrjBisect::solve( double tolerance//The tolerance to halt the bisection iteration. ){ assert(tolerance>0.); int nrepition=0; double span=m_te-m_ts; tolerance+=MGTolerance::mach_zero()*2.; while(fabs(span)>=tolerance){//m_ts > m_te may happend. span*=.5; nrepition++; double t=m_ts+span; compare_replace(t); } return nrepition; } //Obtain the projected curve of a curve onto the surface. //The direction of the projection is along the vector vec if the vec is not //NULL, and normal to the surface if the vec is NULL. //Output of 'project' is two kind of curves: //one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of //the parameter space of the surfaces(vec_crv_uv). //vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then // (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. ///Function's return value is: /// >=0: number of curves obtained, <0 : Some error detected. //戻り値: // 投影曲線の数: 投影曲線が求まった // 0: 投影曲線が求まらなかった // -1: 内部処理エラー // -2: 収束処理エラー(収束しなかった) int MGFSurface::projectbyApproximateAsLBRep( const MGCurve& crv, MGPvector& vec_crv_uv, //Projected curve(surface parameter (u,v) representation) will be appended. MGPvector& vec_crv, //Projected curve(world coordinate(x,y,z) representation) will be appended. const MGVector& vec )const{ //初期化 std::unique_ptr lb(new MGLBRep); crv.approximate_as_LBRep(*lb); if(!vec.is_null()) //ベクトル投影 return projVector(*lb, vec_crv_uv, vec_crv, vec); else return projNormal(*lb, vec_crv_uv, vec_crv); } //Obtain the projected curve of a curve onto the surface. //The direction of the projection is along the vector vec if the vec is not //NULL, and normal to the surface if the vec is NULL. //Output of 'project' is two kind of curves: //one is general world coordinate curves('vec_crv'), and the other is (u,v) curves of //the parameter space of the surfaces(vec_crv_uv). //vec_crv_uv.size() is equal to vec_crv.size(). Let the size be n, then // (vec_crv_uv[i], vec_crv[i]) is one pair for 0<=i=0: number of curves obtained, <0 : Some error detected. int MGFSurface::projectbyRemovKnots( const MGCurve& crv, MGPvector& vec_crv_uv, //Projected curve(surface parameter (u,v) representation) will be appended. MGPvector& vec_crv, //Projected curve(world coordinate(x,y,z) representation) will be appended. const MGVector& vec )const{ //初期化 std::unique_ptr crvRemoveKnot(crv.clone()); crvRemoveKnot->remove_knot(); if(!vec.is_null()) //ベクトル投影 return projVector(*crvRemoveKnot, vec_crv_uv, vec_crv, vec); else return projNormal(*crvRemoveKnot, vec_crv_uv, vec_crv); } //向きが同じ2本のB表現曲線を接続する(同じ種類のとき) MGLBRep* join2LBRep(const MGLBRep& crv1, const MGLBRep& crv2); //向きが同じ5次(xyzuv)のB表現曲線リストを(x,y,z)と(u,v)の2種の曲線に分解し、 //join_crvl_uv, _xyzに格納する。もし、連続する曲線が連続であれば、接続する。 //join_crvl_uv,join_crv_xyzに接続した曲線リストが入る。 //Function's return value is the number of output curves. void prj2Pieces( const MGLBRep& lb5, MGPvector& join_crvl_uv, MGPvector& join_crvl_xyz ){ join_crvl_uv.push_back(new MGLBRep(2,lb5,0,3)); join_crvl_xyz.push_back(new MGLBRep(3,lb5,0,0)); } //向きが同じ5次(xyzuv)のB表現曲線リストを(x,y,z)と(u,v)の2種の曲線に分解し、 //join_crvl_uv, _xyzに格納する。もし、連続する曲線が連続であれば、接続する。 //join_crvl_uv,join_crv_xyzに接続した曲線リストが入る。 //Function's return value is the number of output curves. void prjJoin( MGPvector& crvl, MGPvector& join_crvl_uv, MGPvector& join_crvl_xyz ){ size_t num = crvl.size(); if(!num) return; if(num==1){ //曲線が1本のときの処理 prj2Pieces(*(crvl[0]),join_crvl_uv,join_crvl_xyz); return; } MGLBRep *cur_pcrv; MGLBRep *next_pcrv; cur_pcrv = crvl.release(0); for(size_t i=1; i& vec_crv_uv, //Projected curve(surface parameter (u,v) representation) will be appended. MGPvector& vec_crv, //Projected curve(world coordinate(x,y,z) representation) will be appended. const MGVector& vec )const{ MGPvector mult_crvl; MGPvector temp_vec_crv; //マルチノットになるときは切って投影して再度接続する int num_mult = crv.divide_multi(mult_crvl); for(int i=0; i& crv_xyzuv_vector,//Projected curve of(x,y,z,u,v) will be appended. const MGVector& vec )const{ double extLeng; if(get_surface_pointer()->type() == MGSURFACE_PLANE){ //曲線の中心からベクトル方向の直線を生成する MGStraight centerStraight(MGSTRAIGHT_UNLIMIT,vec,crv.center()); //直線と面との交点を求める MGCSisect_list isectList = isect(centerStraight); if(isectList.size() > 0){ std::list::const_iterator iterIsect = isectList.begin(); MGPosition posIsect = iterIsect->point(); //延長する長さを直線距離+曲線長さにする extLeng = (posIsect - crv.center()).len() + crv.length(); extLeng *= EXTEND_COEF; //安全の為 } }else{ MGBox box(get_box() | crv.box()); extLeng = box.len() * EXTEND_COEF; //安全の為 } if(MGAZero(extLeng / EXTEND_COEF))extLeng = 1.0; //絶対ゼロ以下の場合の処理 std::unique_ptr apCutSrf(crv.sweep(vec, extLeng, -extLeng)); if(!apCutSrf.get()) return 0; double errsave=MGTolerance::set_wc_zero(MGTolerance::line_zero()); MGSSisect_list isectl = isect(*apCutSrf);//std::cout< apCrv2d(ssiter->release_param1()); std::unique_ptr apCrv3d(ssiter->release_line()); MGCurve &crvOth2d = ssiter->param2(); assert(apCrv2d.get() && apCrv3d.get()); //uパラメータが小さい方を始点とする(元カーブの向きと同じにする) double spt = (crvOth2d.start_point())(0), ept = (crvOth2d.end_point())(0); if(spt > ept){ apCrv2d->negate(); apCrv3d->negate(); } //std::cout<<*apCrv2d<<*apCrv3d<box().len(), //ショートアークのチェックをする world_len = apCrv3d->box().len(); if(param_len < srfError || world_len < MGTolerance::wc_zero())continue; const MGLBRep *pCrv2d = dynamic_cast(apCrv2d.get()); const MGLBRep *pCrv3d = dynamic_cast(apCrv3d.get()); assert(pCrv2d && pCrv3d); int bdim = pCrv2d->bdim(); MGBPointSeq bpXYZUV(5,pCrv3d->line_bcoef()); const MGBPointSeq &bpUV = pCrv2d->line_bcoef(); for(int i2=0; i2knot_vector(), bpXYZUV)); } return i; } ///カーブを折れで分割して行い、後で接続する int MGFSurface::projNormal( const MGCurve& crv, MGPvector& vec_crv_uv, MGPvector& vec_crv )const{ MGPvector divided_curves; //マルチノットになるときは切って投影する int n=crv.divide_multi(divided_curves); MGPvector crv_xyzuv_vector;//Projected curve of(x,y,z,u,v). for(int i=0; i& crv_xyzuv_vector//Projected curve of(x,y,z,u,v) will be appended. )const{ //パラメータ範囲を求める std::deque ranges;//ranges[2*i] to ranges[2*i+1] is the projection range. //Let ranges[.]=tuv, then tuv[0] is the parameter of the curve, and (tuv[1], tuv[2]) //is the parameter of this surface (u,v). double sparam = crv.param_s(); int counter=0, rc; do{ MGPosition tuv[2]; rc = prj2GetParamRange(*this,crv,counter,tuv,counter); if(rc==1 || rc==-1){ ranges.push_back(tuv[0]); ranges.push_back(tuv[1]); } }while(rc < 0); //crv1の途中であれば繰り返す //投影を行う while(ranges.size()>=2){ //ranges will be pop_front by prj2OneCurve. MGLBRep* projectedCurve; prj2OneCurve(*this,crv,ranges,projectedCurve); //投影曲線列の冗長ノットを削除して接続する if(projectedCurve) crv_xyzuv_vector.push_back(projectedCurve); } }