/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Unit_vector.h" #include "mg/Matrix.h" #include "mg/CParam_list.h" #include "mg/Position_list.h" #include "mg/CCisect_list.h" #include "mg/CSisect_list.h" #include "mg/PPRep.h" #include "mg/Straight.h" #include "mg/Ellipse.h" #include "mg/RLBRep.h" #include "mg/BSumCurve.h" #include "mg/SurfCurve.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 // Implements MGRLBRep Class // // Defines Rational Line B-Representation. // This NURBS is of homogeneous form, i.e., B-Coefficients have // weight included values. // When usual NURBS form is (xi, yi, zi, wi) , // MGRLBRep form is (xi*wi, yi*wi, zi*wi, wi) for i=0,..., n-1. ///Approximate this curve as a MGLBRep curve ///within the tolerance MGTolerance::line_zero(). ///When parameter_normalization=0, reparameterization will not done, and ///the evaluation at the same parameter has the same values before and after ///of approximate_as_LBRep. void MGRLBRep::approximate_as_LBRep( MGLBRep& lb, ///& crv_list, //divided curves will be appended. int multiplicity //designates the multiplicity of the knot to divide at. //When multiplicity<=0, order()-1 is assumed. //When multiplicity>=order(), order() is assumed. )const{ MGPvector crv_list2; int n=m_line.divide_multi(crv_list2,multiplicity); for(int i=0; i(crv_list2[i])); crv_list.push_back(new MGRLBRep(lbi,1)); } return n; } //Modify the original NURBS by extrapolating the specified perimeter. //The extrapolation is C2 continuous if the order >=4. MGRLBRep& MGRLBRep::extend( int start, //Flag of start or end poit of the line. //If start is true extend on the start point. double length, //chord length to extend. 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. ){ double t,tau,vlen; if(start){ t=param_s(); vlen=eval(t,1).len(); if(MGMZero(vlen)) return *this; tau=t-length/vlen; }else{ t=param_e(); vlen=eval(t,1).len(); if(MGMZero(vlen)) return *this; tau=t+length/vlen; } extend_with_parameter(tau,dk); return *this; } //Extrapolate this curve by an (approximate) chord length. //The extrapolation is C2 continuous. void MGRLBRep::extend( double length, //approximate chord length to extend. bool start //Flag of which point to extend, start or end point of the line. //If start is true extend on the start point. ){ int se=start ? 1:0; extend(se,length,0.); } //Extrapolate the curve by the parameter value. MGRLBRep& MGRLBRep::extend_with_parameter( double tau, //The parameter value at the end of extended point. //When tauparam_e(), extension will be done at the end point. double dk //Coefficient of how curvature should vary at the connecting point. //See extend(); ){ MGPPRep pp; extrapolated_pp(tau,dk,pp); MGLBRep lbext(pp);//std::cout<(&curve2); if(sl11) return sl11->is_coplanar(*this,plane); const MGLBRep* lb11=dynamic_cast(&curve2); if(lb11) return lb11->is_coplanar(*this,plane); MGPosition point; MGStraight sl1; int plkind=planar(plane,sl1,point); if(plkind==0) return false; MGPosition point2; MGStraight sl2; int plkind2=-1; MGPlane plane2; MGPosition uv; const MGRLBRep* rlb=dynamic_cast(&curve2); if(rlb){ plkind2=rlb->planar(plane2,sl2,point2); if(plkind2==0) return false; if(plkind2==1){ if(plkind==1){ plane=MGPlane(point,point2,point); return true; }else if(plkind==2){ plane=MGPlane(sl1,point2); return true; }else{ return plane.on(point2,uv); } }else if(plkind2==2){ if(plkind==1){ plane=MGPlane(sl2,point); return true; }else if(plkind==2){ return sl1.is_coplanar(sl2,plane); }else{ return plane.on(sl2); } }else{ if(plkind==1){ plane=plane2; return plane.on(point,uv); }else if(plkind==2){ plane=plane2; return plane.on(sl1); }else{ return plane==plane2; } } }else{ if(!curve2.is_planar(plane2)) return false; if(plkind==1){ plane=plane2; return plane.on(point,uv); }else if(plkind==2){ plane=plane2; return plane.on(sl1); } return plane2==plane; } } //Test if this cure is planar or not. //MGPlane expression will be out to plane if this is planar. //Function's return value is true if planar. bool MGRLBRep::is_planar(MGPlane& plane)const{ MGStraight line; MGPosition point; int isp=planar(plane,line,point); if(isp==1){//IF this is within a point. plane=MGPlane(mgZ_UVEC,point); }else if(isp==2){//IF this is within a straight. return line.is_planar(plane); } return isp>0; } //Spline と Curve の交点を求める。 //Intersection point of NURBS and curve. MGCCisect_list MGRLBRep::isect(const MGCurve& curve2) const{ MGCCisect_list list=curve2.isect(*this); return list.replace12(); } //Intersection point of NURBS and straight line. MGCCisect_list MGRLBRep::isect(const MGStraight& sline) const{ MGCCisect_list list(this,&sline); if(!has_common(sline)) return list; MGCParam_list clist; double errsave=MGTolerance::wc_zero(); MGTolerance::set_wc_zero(errsave*.3);//make error smaller. if(sdim()<=2 && sline.sdim()<=2) clist=isect_2D(sline); else { MGPlane plane(sline, mgORIGIN); //The plane that includes sline and passes through the origin. clist=isect_3D(plane); } MGTolerance::set_wc_zero(errsave); //Retrieve error. MGPosition p; double t1,t2; MGCParam_list::Citerator i; for(i=clist.begin(); i!=clist.end(); i++){ t1=(*i); p=eval(t1); if(sline.on(p,t2)) list.append(MGCCisect(p,t1,t2)); } return list; } //Spline と Curve の交点を求める。 //Intersection point of NURBS and curve. MGCCisect_list MGRLBRep::isect(const MGSurfCurve& curve2) const{ MGCCisect_list list=curve2.isect(*this); return list.replace12(); } //Spline と Curve の交点を求める。 //Intersection point of NURBS and curve. MGCCisect_list MGRLBRep::isect(const MGBSumCurve& curve2) const{ MGCCisect_list list=curve2.isect(*this); return list.replace12(); } //Intersection of Spline and Surface MGCSisect_list MGRLBRep::isect(const MGSurface& surf)const{ return surf.isect(*this); } MGCSisect_list MGRLBRep::isect(const MGPlane& plane) const{ MGCSisect_list list(this,&plane); MGCParam_list clist=isect_3D(plane); double tt; MGPosition p, uvpl; int inum=clist.entries(); for(int i=0; iw_id) ncod=w_id; cod[0]=coordinate; for(j=1; j=w_id) cod[j]=0; } for(j=ncod; jmax) max=x; } double error=MGTolerance::wc_zero(); if(max<-error || min>error) return MGCParam_list(); // std::cout< MGRLBRep::oneD( const double g[4] //Plane expression(a,b,c,d) where ax+by+cz=d. )const{ int i, nbd=bdim(); int j, w_id=sdim(); int k=order(); int ncod=3; if(ncod>w_id) ncod=w_id; const MGBPointSeq& cf=m_line.line_bcoef(); MGLBRep* brep=new MGLBRep(); MGBPointSeq& rcoef=brep->line_bcoef(); rcoef.resize(nbd,1); MGKnotVector& knotv=brep->knot_vector(); knotv.size_change(k,nbd); double min,max; const MGKnotVector& t=knot_vector(); double rt=0.; for(j=0; jrt) min=rt; if(max(brep); } //Compute all the perpendicular points of this curve and the second one. //That is, if f(s) and g(t) are the points of the two curves f and g, //then obtains points where the following conditions are satisfied: // fs*(f-g)=0. gt*(g-f)=0. //Here fs and gt are 1st derivatives at s and t of f and g. //MGPosition P in the MGPosition_list contains this and crv2's parameter //as: P(0)=this curve's parameter, P(1)=crv2's parameter value. MGPosition_list MGRLBRep::perps( const MGCurve& crv2 //The second curve )const{ MGPosition_list list=crv2.perps(*this); return MGPosition_list(list,1,0); } MGPosition_list MGRLBRep::perps( const MGStraight& crv2 //The second curve )const{return perpsSl(crv2);}