/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Position_list.h" #include "mg/CCisect_list.h" #include "mg/CSisect_list.h" #include "mg/LBRep.h" #include "mg/RLBRep.h" #include "mg/SurfCurve.h" #include "mg/BSumCurve.h" #include "mg/Transf.h" #include "mg/Plane.h" #include "mg/SPhere.h" #include "mg/Cylinder.h" #include "mg/SBRep.h" #include "mg/RSBRep.h" #include "mg/BSumSurf.h" #include "mg/Tolerance.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif using namespace std; // MGCylinder.cpp // Implementation of class MGCylinder //MGCylinder is a Cylinder in 3D space. //Cylinder is expressed by an ellipse and a straight line. //Cylinder function f(u,v) = m_ellipse(u) + m_axis(v), //where u and v are two parameter of surface representation. //Here, m_axis is a straight line that passes through the origin. //m_axis'es m_root_point is always set to the origin. //m_ellise is the ellipse when v=0(when v=0, m_axis(v)=the origin); // MGCylinderクラスは3次元空間における円筒面を表すクラスである。 // MGCylinderクラスでは以下のようなパラメータ表現を使用します。 // f(u,v) = m_ellipse(u) + m_axis(v); /////////////Constructor コンストラクタ//////////// //Void constructor 初期化なしで柱面を生成する。 MGCylinder::MGCylinder(void):MGSurface(){;} // Construct a Cylinder by changing this space dimension or // ordering the coordinates. MGCylinder::MGCylinder( int dim, // New space dimension. const MGCylinder& cyl, // Original Cylinder. int start1, // Destination order of new Surface. int start2) // Source order of original Surface. :MGSurface(cyl),m_ellipse(dim,cyl.m_ellipse,start1,start2), m_axis(dim,cyl.m_axis,start1,start2){ update_mark(); m_ortho=m_ellipse.normal().parallel(m_axis.direction()); } // Construct a cylinder of whole circle whose bottom center is bottom //and top center is bottom+axis. MGCylinder::MGCylinder( const MGPosition& bottom, //Location on axis to position the cylinder, //defines zero v. const MGVector axis,//The axis vector for the cylinder. double radius, //The radius of the cylinder. bool outgoing //Indicates if the surface normal is going to //outside of the cylinder(true) or inside(false). ):MGSurface(),m_ellipse(bottom,radius,axis), m_axis(mgORIGIN+axis,mgORIGIN), m_ortho(true){ if(!outgoing) m_ellipse.negate(); } //Cylinder from an ellipse and the axis straight line. //When axis'es start point is not ellipse's center, axis'es start point //will be set to the center. MGCylinder::MGCylinder( const MGEllipse& ellipse, //ellispe of the cylinder const MGStraight& axis //axis of the cylinder. //axis's root point will be neglected, always be set as //the origin. ):MGSurface(),m_ellipse(ellipse),m_axis(axis){ m_axis.m_root_point=mgORIGIN; m_ortho=m_ellipse.normal().parallel(axis.direction()); } //////////Operator overload 演算子の多重定義///////////// //Assignment. //When the leaf object of this and srf2 are not equal, this assignment //does nothing. MGCylinder& MGCylinder::operator=(const MGCylinder& gel2){ if(this==&gel2) return *this; MGSurface::operator=(gel2); m_axis=gel2.m_axis; m_ellipse=gel2.m_ellipse; m_ortho=gel2.m_ortho; return *this; } MGCylinder& MGCylinder::operator=(const MGGel& gel2){ const MGCylinder* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) operator=(*gel2_is_this); return *this; } //Translation of the Cylinder MGCylinder MGCylinder::operator+ (const MGVector& vec) const{ return MGCylinder(m_ellipse+vec,m_axis); } MGCylinder operator+ (const MGVector& v, const MGCylinder& cyl){ return cyl+v; } //Translation of the Cylinder MGCylinder& MGCylinder::operator+= (const MGVector& vec){ m_ellipse+=vec; if(m_box) (*m_box)+=vec; return *this; } //Translation of the Cylinder MGCylinder MGCylinder::operator- (const MGVector& vec) const{ return MGCylinder(m_ellipse-vec,m_axis); } //Translation of the Cylinder MGCylinder& MGCylinder::operator-= (const MGVector& vec){ m_ellipse-=vec; if(m_box) (*m_box)-=vec; return *this; } //柱面のスケーリングを行い,柱面を作成する。 //Scaling of the Cylinder by a double. MGCylinder MGCylinder::operator* (double s) const{ return MGCylinder(m_ellipse*s, m_axis*s); } //Scaling of the Cylinder by a double. MGCylinder operator* (double scale, const MGCylinder& cyl){ return cyl*scale; } //Scaling of the Cylinder by a double. MGCylinder& MGCylinder::operator*= (double s){ m_ellipse*=s; m_axis*=s; update_mark(); return *this; } //Transformation of the Cylinder by a matrix. MGCylinder MGCylinder::operator* (const MGMatrix& mat) const{ return MGCylinder(m_ellipse*mat, m_axis*mat); } //Transformation of the Cylinder by a matrix. MGCylinder& MGCylinder::operator*= (const MGMatrix& mat){ m_ellipse*=mat; m_axis*=mat; m_ortho=m_ellipse.normal().parallel(m_axis.direction()); update_mark(); return *this; } //Transformation of the Cylinder by a MGTransf. MGCylinder MGCylinder::operator* (const MGTransf& tr) const{ return MGCylinder(m_ellipse*tr, m_axis*tr.affine()); } //Transformation of the Cylinder by a MGTransf. MGCylinder& MGCylinder::operator*= (const MGTransf& tr){ m_ellipse*=tr; m_axis*=tr.affine(); m_ortho=m_ellipse.normal().parallel(m_axis.direction()); update_mark(); return *this; } //Comparison between Cylinder and a surface. bool MGCylinder::operator==(const MGCylinder& srf2)const{ if(m_ellipse!=srf2.m_ellipse) return false; if(m_axis!=srf2.m_axis) return false; return true; } bool MGCylinder::operator<(const MGCylinder& gel2)const{ if(m_ellipse==gel2.m_ellipse) return m_axis(&gel2); if(gel2_is_this) return operator==(*gel2_is_this); return false; } bool MGCylinder::operator<(const MGGel& gel2)const{ const MGCylinder* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) return operator<(*gel2_is_this); return false; } /////////Debug function デバッグ関数/////////// // Output virtual function. //Output to ostream メンバデータを標準出力に出力する。 std::ostream& MGCylinder::out(std::ostream &outpt) const{ outpt<<"MGCylinder::"<=4. //The extrapolation is done so that extrapolating length is "length" //at the position of the parameter value "param" of the perimeter. MGCylinder& MGCylinder::extend( int perimeter, //perimeter number of the Surface. // =0:v=min, =1:u=max, =2:v=max, =3:u=min. double param, // parameter value of above perimeter. double length, //chord length to extend at the parameter param of the perimeter. double dk){ //Coefficient of how curvature should vary at // extrapolation start point. When dk=0, curvature keeps same, i.e. // dK/dS=0. When dk=1, curvature becomes zero at length extrapolated point, // i.e. dK/dS=-K/length at extrapolation start point. // (S=parameter of arc length, K=Curvature at start point) // That is, when dk reaches to 1 from 0, curve changes to flat. assert(0<=perimeter && perimeter<4); bool is_start=true;//starting perimeter MGCurve* to_extend; int ndu=0,ndv=0; if(perimeter==1 || perimeter==3){ // Extrapolate to u-direction to_extend=&m_ellipse; if(perimeter==1) is_start=false;//ending perimeter ndu=1; }else{ // Extrapolate to v-direction to_extend=&m_axis; if(perimeter==2) is_start=false;//ending perimeter ndv=1; } MGPosition uv=perimeter_uv(perimeter,param);//Surface parameter value of param. double vlen=eval(uv,ndu,ndv).len(); double slen=length/vlen; to_extend->extend(slen,is_start); return *this; } //Test if the surface is flat or not within the parameter value rectangle of uvbox. //Function's return value is: // true: if the surface is flat, // false: if the surface is not falt. //When this is not falt, the direction that indicates which direction the surface //should be divided will be output. //***** the flatness is tested only approximately. This is for exclusive use of //planar(). bool MGCylinder::flat( const MGBox& uvbox, double tol, //Tolerance allowed to regard flat //(Allowed distance from a Cylinder). int& direction, // 1: u-direction is more non flat. // 0: v-direction is more non flat. MGPosition& P, //Position of the flat plane will be output. MGUnit_vector& N//Normal of the flat plane will be output. )const{ direction=1; N=normal(uvbox.mid()); const MGInterval& urange=uvbox[0]; const MGInterval& vrange=uvbox[1]; MGEllipse el(mgORIGIN_2D, MGVector(m_ellipse.major_len(),0.), MGVector(0.,m_ellipse.minor_len()), urange); const MGBox& elbx=el.box(); P=elbx.mid(); P+=m_ellipse.center(); P+=m_axis.eval(vrange.mid_point()); double a=elbx[0].length().value(), b=elbx[1].length().value(); if(aa2) a=a2; } return a<=tol; } //This is the same as flat except that this does not have the arguments P, N. //***** the flatness is tested only approximately. This is for exclusive use of //tessellation. bool MGCylinder::flat_tess( double u0,double u1, //u range from u0 to u1. double v0,double v1, //v range from v0 to v1. double tol, //Tolerance allowed to regart flat //(Allowed distance from a Cylinder). bool& direction,// 1: u-direction is more non flat. // 0: v-direction is more non flat. double max_edge_len )const{ direction=true; double um=(u0+u1)*0.5; int i; //id of Pn[]. MGVector Pn[3], Nn[3]; Pn[0]=eval(u0, v0); Nn[0]=normal(u0,v0); Pn[1]=eval(um, v0); Nn[1]=normal(um,v0); Pn[2]=eval(u1, v0); Nn[2]=normal(u1,v0); MGVector P=Pn[0]; MGVector VN=Nn[0]; for(i=1; i<3; i++){P+=Pn[i]; VN+=Nn[i];} P/=3.; MGUnit_vector N(VN); double x, d=P%N; double dist[3]; bool is_flat=true; for(i=0; i<3; i++){ x=dist[i]=d-Pn[i]%N; if(x<0.) x=-x; if(x>tol) is_flat=false; } if(is_flat){ MGVector P02(Pn[2],Pn[0]); double lenu=P02%P02; MGVector axisV=m_axis.eval(v0)-m_axis.eval(v1); double lenv=axisV%axisV; direction=lenu>=lenv; if(max_edge_len<=0.) return true; double melen2=max_edge_len; melen2*=melen2; if(direction){ if(lenu>melen2) return false; }else{ if(lenv>melen2) return false; } return true; } return false; } bool MGCylinder::in_range(double u, double v) const{ return m_ellipse.in_range(u) && m_axis.in_range(v); } // Surface と Curve の交点を求める。 //Compute intesection of Cylinder and Curve. MGCSisect_list MGCylinder::isect(const MGCurve& curve) const{ return curve.isect(*this); } // Surface と Curve の交点を求める。 //Compute intesection of Cylinder and Curve. MGCSisect_list MGCylinder::isect(const MGRLBRep& curve) const{ return curve.isect(*this); } // Surface と Curve の交点を求める。 //Compute intesection of Cylinder and Curve. MGCSisect_list MGCylinder::isect(const MGEllipse& curve) const{ return curve.isect(*this); } // Surface と Curve の交点を求める。 //Compute intesection of Cylinder and Curve. MGCSisect_list MGCylinder::isect(const MGLBRep& curve) const{ return curve.isect(*this); } // Surface と Curve の交点を求める。 //Compute intesection of Cylinder and Curve. MGCSisect_list MGCylinder::isect(const MGSurfCurve& curve) const{ return curve.isect(*this); } // Surface と Curve の交点を求める。 //Compute intesection of Cylinder and Curve. MGCSisect_list MGCylinder::isect(const MGBSumCurve& curve) const{ return curve.isect(*this); } // Surface と Surface の交線を求める。 //Compute intesection of Sphere and Surface. MGSSisect_list MGCylinder::isect(const MGSurface& srf2) const{ MGSSisect_list list=srf2.isect(*this); list.replace12(); return list; } MGSSisect_list MGCylinder::isect(const MGPlane& srf2) const{ return intersectPl(srf2); } MGSSisect_list MGCylinder::isect(const MGSphere& srf2) const{ return intersect(srf2); } MGSSisect_list MGCylinder::isect(const MGCylinder& srf2) const{ return intersect(srf2); } MGSSisect_list MGCylinder::isect(const MGSBRep& srf2) const{ return intersect(srf2); } MGSSisect_list MGCylinder::isect(const MGRSBRep& srf2) const{ return intersect(srf2); } MGSSisect_list MGCylinder::isect(const MGBSumSurf& srf2) const{ return intersect(srf2); } //isect_direction() is used by isect_startPt() to define which constant //parameter line should be used to compute intersection, and what //incremental value be used for the parameter. //Function's return value is direction to get next intersection(with dt). //When =1: u=const direction, =0: v=const, =-1: cannot get intersection. int MGCylinder::isect_direction( const MGFSurface& sf2, //Second surface for the intersection. int m1, //id of uvuvS that indicates this surface's parameter //position in uvuvS. (uvuvS(m1), uvuvS(m1+1))=(u,v) of this surface. MGPosition& uvuvS,//start parameter (u,v) pair of this surface and sf2. double& du, //Incremental value of the parameter kind of kdt will be output. double& dv, //Right dt will be output according to the function's output =0,1. double acuRatio //acuracy ratio. )const{ const MGPlane* pl=dynamic_cast(&sf2); if(!pl) return MGFSurface::isect_direction(sf2,m1,uvuvS,du,dv,acuRatio); double du2,dv2; isect_dt(uvuvS[m1],uvuvS[m1+1],du2,dv2,acuRatio); du=du2; dv=dv2; const MGUnit_vector& pln=pl->normal(); MGUnit_vector axisv=m_axis.direction(); double angl=pln%axisv; if(fabs(angl)<.01) return 0; return 1; } #define MGCylinder_isect_div_num1 12. #define MGCylinder_isect_div_num2 5. //isect_dt computes incremental values of u and v direction for the intersection //computation at parameter position (u,v). void MGCylinder::isect_dt( double u, double v, double& du, double& dv, double acuRatio //acuracy ratio. )const{ double alfa=isect_dt_coef(0); du=m_ellipse.param_span()/MGCylinder_isect_div_num1*alfa*acuRatio; dv=m_axis.param_span()/MGCylinder_isect_div_num2*alfa*acuRatio; } //"isect1_incr_pline" is a dedicated function of isect_start_incr, will get // shortest parameter line necessary to compute intersection. MGCurve* MGCylinder::isect_incr_pline( const MGPosition& uv, //last intersection point. int kdt, //Input if u=const v-parameter line or not. // true:u=const, false:v=const. double du, double dv,//Incremental parameter length. double& u, //next u value will be output double& v, //next v value will be output int incr //Incremental valuse of B-coef's id. ) const{ //Compute necessary sub-interval length of parameter line of this surface. if(kdt){ u=m_ellipse.range(uv[0]+du); v=uv[1]; //Compute u=const v-parameter line of this surface in pline. return parameter_curve(kdt,u); }else{ v=m_axis.range(uv[1]+dv); u=uv[0]; //Compute v=const u-parameter line in pline. return parameter_curve(kdt,v); } } //"isect_inner_dt" is a dedicated function of isect_startPt, // comutes adequate incremental parameter value(du,dv) and parameter line kind //kdt(u=const or v=const). void MGCylinder::isect_inner_dt( int n, //num of i.p. obtained so far(not include uvnow). const MGPosition& uvnow,//intersection point obtained last(of this). double& du, double& dv, //incremental length from previous to uvnow is input. //New du or dv will be output according to kdt's return value. int& kdt, //Parameter kind used so far is input, will be output as: //=1:parameter line kind(u=const), =0: v=const, //=-1:should halt computation since incremental value is zero. double acuRatio //Accurate ratio. ) const{ double uerr=param_error_u(); double verr=param_error_v(); double abdu=fabs(du), abdv=fabs(dv); double ratio=acuRatio; if(abdu 2.*dtr2) dt=dtold*2.; else if(dtr1 < .5*dtr2) dt=dtold*.5; } if(kdt) du=dt; else dv=dt; return; } typedef MGPosition_list::iterator plitr; bool uvcompare(plitr i1,plitr i2){return (*i1)[0]<(*i2)[0];}; //Compute the intersection line of this and the plane pl. MGSSisect_list MGCylinder::intersectPl(const MGPlane& pl)const{ MGSSisect_list lst(this,&pl); MGPosition_list uvuv_list2; double error=MGTolerance::set_wc_zero(MGTolerance::line_zero()*.5); //Save the error. isect_boundary(pl,uvuv_list2); MGTolerance::set_wc_zero(error);//Restore the error. int numi=uvuv_list2.size(); if(numi){ int j; std::vector iss(numi); plitr i=uvuv_list2.begin(), ie=uvuv_list2.end(); for(j=0; j1){ plitr pi=uvuv_list.begin(); MGPosition& uvuv1=*(pi++); MGPosition& uvuv2=*pi; if(MGREqual_base(uvuv1[0], uvuv2[0], uspan)){ MGCurve* iline= new MGStraight(pl.eval(uvuv2[2],uvuv2[3]),pl.eval(uvuv1[2],uvuv1[3])); double t1=iline->param_s(), t2=iline->param_e(); MGCurve* param1= new MGStraight(MGPosition(uvuv2[0],uvuv2[1]), MGPosition(uvuv1[0],uvuv1[1])); param1->change_range(t1,t2); MGCurve* param2= new MGStraight(MGPosition(uvuv2[2],uvuv2[3]), MGPosition(uvuv1[2],uvuv1[3])); param2->change_range(t1,t2); lst.append(iline,param1,param2); uvuv_list.pop_front(); uvuv_list.pop_front(); }else if(fabs(uvuv1[1]-uvuv2[1])<=verr){ MGCurve* iline= new MGEllipse(m_ellipse+m_axis.eval(uvuv1[1])); double t1=iline->param_s(), t2=iline->param_e(); MGCurve* param1= new MGStraight(MGPosition(uvuv2[0],uvuv2[1]), MGPosition(uvuv1[0],uvuv1[1])); param1->change_range(t1,t2); MGPosition elcenter=iline->eval((t1+t2)*.5); MGPosition pluvc; pl.on(elcenter,pluvc); MGCurve* param2= new MGEllipse( MGPosition(uvuv1[2],uvuv1[3]), //Starting point pluvc, MGPosition(uvuv2[2],uvuv2[3]));//Ending point param2->change_range(t1,t2); lst.append(iline,param1,param2); uvuv_list.pop_front(); uvuv_list.pop_front(); }else{ lst.append(isect_with_surf(uvuv_list,pl)); } } } return lst; } //Intersection of Surface and a straight line. MGCSisect_list MGCylinder::isectSl( const MGStraight& sl, const MGBox& uvbox //indicates if this surface is restrictied to the parameter //range of uvbox. If uvbox.is_null(), no restriction. )const{ assert(m_ortho);//currently, m_axis must be orthogonal to m_ellipse. //std::cout<(parameter_curve(true,u)); MGStraight slcyl2(2,(*slcyl)*mat2);//std::cout< MGCylinder::offset_c1( double ofs_value, //オフセット量 int& error//エラーコード 0:成功 -1:面におれがある* // -2:曲率半径以上のオフセット不可 -3:面生成コンストラクタエラー )const{ MGVector S=m_ellipse.eval(m_ellipse.param_s(),1); const MGVector& M=m_ellipse.major_axis(); const MGVector& A=m_axis.direction(); if((S*A)%M <0.) ofs_value*=-1.; double r1=m_ellipse.m_r; double r2=r1+ofs_value; if(r2<=0.){ error=-2; return std::unique_ptr(); } MGEllipse el2(m_ellipse); double scale=r2/r1; el2.m_m*=scale; el2.m_n*=scale; el2.m_r*=scale; el2.update_mark(); std::unique_ptr surf(new MGCylinder(el2,m_axis)); return surf; } // 指定点が面上にあるか調べる。(面上ならばtrue) //Test if a point is on the Cylinder. If on the Cylinder, return true. bool MGCylinder::on( const MGPosition& point, //A point to test 指定点 MGPosition& puv //Parameter value of the Cylinder will be //returned. )const{ puv=closest(point); return ((point-eval(puv)).len()<=MGTolerance::wc_zero()); } //Test if input (u,v) is parameter value on a perimeter of the surface. //If u or v is on a perimeter, (u,v) will be updated to the perimeter value. bool MGCylinder::on_a_perimeter( double& u, double& v, //Surface parameter (u,v) int& perim_num //if function returns true, //the perimete rnumber is output. )const{ if(!in_range(u,v)) return false; MGSTRAIGHT_TYPE slt=m_axis.straight_type(); if(slt!=MGSTRAIGHT_UNLIMIT){ double vspan=m_axis.param_span(); double v0=m_axis.param_s(); if(MGREqual_base(v,v0,vspan)){ perim_num=0; v=v0; return true; } if(slt!=MGSTRAIGHT_HALF_LIMIT){ double v1=m_axis.param_e(); if(MGREqual_base(v,v1,vspan)){ perim_num=2; v=v1; return true; } } } double uspan=m_ellipse.param_span(); double u0=m_ellipse.param_s(); if(MGREqual_base(u,u0,uspan)){ perim_num=3; u=u0; return true; } double u1=m_ellipse.param_e(); if(MGREqual_base(u,u1,uspan)){ perim_num=1; u=u1; return true; } return false; } //Obtain parameter space error. double MGCylinder::param_error() const{ double uerror=m_ellipse.param_error(); double verror=m_axis.param_error(); return sqrt(uerror*uerror+verror*verror); } // パラメータ範囲を返す。 //Return parameter range of the Cylinder(Infinite box). MGBox MGCylinder::param_range() const{ return MGBox(m_ellipse.param_range(), m_axis.param_range()); } // Compute parameter curve. //Returned is newed area pointer, and must be freed by delete. MGCurve* MGCylinder::parameter_curve( int is_u //Indicates x is u-value if is_u is true. , double x //Parameter value. //The value is u or v according to is_u. )const{ if(is_u){ MGStraight* sl=new MGStraight(m_axis); sl->m_root_point=m_ellipse.eval(x); return sl; }else{ MGEllipse* el=new MGEllipse(m_ellipse); el->m_center+=m_axis.eval(x); return el; } } //Compute part of the surface limitted by the parameter range bx. //bx(0) is the parameter (us,ue) and bx(1) is (vs,ve). //That is u range is from us to ue , and so on. MGCylinder* MGCylinder::part( const MGBox& uvbx, int multiple //Indicates if start and end knot multiplicities //are necessary. =0:unnecessary, !=0:necessary. )const{ MGCylinder* cyl=new MGCylinder(*this); cyl->m_ellipse.limit(uvbx[0]); cyl->m_axis.limit(uvbx[1]); return cyl; } // i must be < perimeter_num(). //When perimeter_num()==0, this function is undefined. MGCurve* MGCylinder::perimeter_curve(int i) const{ if(i==0){ return new MGEllipse(m_ellipse+m_axis.start_point()); }else if(i==2){ return new MGEllipse(m_ellipse+m_axis.end_point()); }else if(i==1){ return new MGStraight(m_axis+m_ellipse.end_point()); }else{ return new MGStraight(m_axis+m_ellipse.start_point()); } } // 与えられた点にもっとも近い面上の垂直のパラメータ値を返却する。 //Return the nearest perpendicular point of the Cylinder from P. // Function's return value is whether point is obtained(1) or not(0) int MGCylinder::perp_point( const MGPosition& P,// 与えられた点 MGPosition& uv, //Parameter value of the Cylinder will be output const MGPosition* uvguess // guess )const{ assert(m_ortho); double v; int obtained; int range=vrange(P,v); MGEllipse el(m_ellipse); if(range==1){ el+=m_axis.end_point(); obtained=0; }else if(range==-1){ el+=m_axis.start_point(); obtained=0; }else{ el+=m_axis.eval(v); obtained=1; } double u=el.closest(P); uv=MGPosition(u,v); return obtained; } //Return all(actually one) foots of perpendicular straight lines from P. MGPosition_list MGCylinder::perps( const MGPosition& P // Point of a space(指定点) ) const{ assert(m_ortho); MGPosition_list list; double v; int vinrange=vrange(P,v); if(vinrange==0){ MGPosition p2d= P*MGTransf(m_ellipse.major_axis(), m_ellipse.minor_axis(),axis_point(v)); double theta[4]; // Intersection points are maixmum 4. int nump=m_ellipse.perp2d(p2d.ref(0), p2d.ref(1), theta); for(int i=0; iv){ v=vrng[0].value(); obtained=-1; }else{ obtained=0; } return obtained; } //メンバデータを読み込む関数 void MGCylinder::ReadMembers(MGIfstream& buf){ MGSurface::ReadMembers(buf); m_ellipse.ReadMembers(buf); m_axis.ReadMembers(buf); } //メンバデータを書き込む関数 void MGCylinder::WriteMembers(MGOfstream& buf) const{ MGSurface::WriteMembers(buf); m_ellipse.WriteMembers(buf); m_axis.WriteMembers(buf); }