/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Box.h" #include "mg/Position.h" #include "mg/KnotArray.h" #include "mg/CParam_list.h" #include "mg/BPointSeq.h" #include "mg/OscuCircle.h" #include "mg/Ellipse.h" #include "mg/Straight.h" #include "mg/PPRep.h" #include "mg/LBRepEndC.h" #include "mg/LBRep.h" #include "mg/RLBRep.h" #include "mg/TrimmedCurve.h" #include "mg/SurfCurve.h" #include "mg/Tolerance.h" #include "cskernel/Bluprt.h" #include "cskernel/Blumix.h" #include "cskernel/bkdtpg.h" #include "cskernel/Bludkt.h" #include "cskernel/Bluakt.h" #include "cskernel/Blgl2a.h" #include "cskernel/Blgint.h" #include "cskernel/Bkdnp.h" #include "cskernel/bkdtkt.h" #include "cskernel/Blctpb.h" #include "cskernel/blg4sc.h" #include "cskernel/blg4sp2.h" #include "cskernel/blgcs.h" #include "cskernel/mgblgsq.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif using namespace std; // MGLBRep.cpp // // Implement MGLBRep class. // // This file contains all of the constructors of MGLBRep. //<< Constructor >> //Construct Line B-Representation, providing all the data. MGLBRep::MGLBRep( const MGKnotVector& t, //Knot Vector. const MGBPointSeq& bcoef //Line B-Coef. ):MGCurve(), m_knot_vector(t), m_line_bcoef(bcoef){ assert(t.bdim()==bcoef.length()); } //**** 1. Interpolation Constructor **** ///Construct Line B-rep by intepolation from Point data only. ///If circular is true, start and end points must be the same, ///(that is points[0]==points[n-1]) and the MGLBRep constructed is ///smoothly connected at the point. ///If circular is true, order will be always 4, and input order is neglected. MGLBRep::MGLBRep( const MGBPointSeq& points,//Point seq data int order, // Order bool circular ///=2 && points.length()>=2); MGBPointSeq points_temp(points);//Copy, since BLG4SC, BLGSPL may change //input data. int nv=points_temp.length(); //Number of input points. const int iv=points_temp.capacity(); const int ncd=points_temp.sdim(); const int irc=m_line_bcoef.capacity(); int n; int error=2;//When order=2 is input, error stays equal to 2. if(circular){ if(order!=4) m_knot_vector.change_order(4); double* work1=new double[irc]; double* work2=new double[irc*9]; blg4sc_(nv, &points_temp(0,0), iv, ncd, irc, work1,work2, &n, &m_knot_vector(0), &m_line_bcoef(0,0), &error); delete[] work1; delete[] work2; }else if(order>2){ if(nvratio or // d(i-1)/d(i)>ratio, either tau[i] or tau[i-1] will be removed. // This is done to prevent control polygon computation error. // When ratio<0. no data point removal will be done. ):MGCurve(),m_line_bcoef(points.length(),points.sdim()){ int IMLT=1; MGNDDArray tau2(tau); MGBPointSeq points2(points); int n=points2.length(), pointSize=points2.capacity(), pointDim=points2.sdim(); if(ratio>0.){ bkdnp_((int*)&n,tau2.data(),points2.data(),pointSize,pointDim,IMLT,ratio); tau2.set_length(n); points2.set_length(n); } int k=order;//Order if(k>n) k=n; m_knot_vector=MGKnotVector(tau2,k); double* work=new double[n*(2*k-1)]; const int irc=m_line_bcoef.capacity(); int error=blgint_(tau2.data(), points2.data(), m_knot_vector.data(), k, n, pointDim, pointSize, irc, work, &m_line_bcoef(0,0)); delete[] work; if(error==1){ error=0; //Return of BLGINT error=1 means normal. m_line_bcoef.set_length(n); }else{ //Generate polyline B-Rep. of order 2. //When error detected, the polyline that connects input points is set. m_knot_vector=MGKnotVector(2,n,0.,1.); m_line_bcoef=points2; } } //Construct Line B-rep of any order number by interpolation //from data point and knot vector. MGLBRep::MGLBRep( const MGNDDArray& tau, //Data point abscissa const MGBPointSeq& points, //Point seq data const MGKnotVector& t //knot vector ):MGCurve(), m_knot_vector(t),m_line_bcoef(points.length(),points.sdim()){ const int k=t.order(); const int n=points.length(); const int ncd=points.sdim(); const int iv=points.capacity(); const int irc=m_line_bcoef.capacity(); double* work=new double[n*(2*k-1)]; int error=blgint_(tau.data(), points.data(), t.data(), k, n, ncd, iv, irc, work, &m_line_bcoef(0,0)); delete[] work; if(error==1){ m_line_bcoef.set_length(n); }else{ //Generate polyline B-Rep. of order 2. //When error detected, the polyline that connects input points is set. m_knot_vector=MGKnotVector(2,n,0.,1.); m_line_bcoef=points; } } void build_mgblgsp_parameter( int& order, //Order of the target B-Spline. const MGLBRepEndC& begin, //Begin end condition const MGLBRepEndC& end, //End end conditoion const MGNDDArray& tau, //Data point abscissa const MGBPointSeq& value, //Data point ordinate MGENDCOND& beginc, MGENDCOND& endc, MGNDDArray& tau_new, //Data point abscissa MGBPointSeq& value_new //Data point ordinate. //value_new.size() wil be value.length(). ){ int i,j; int ie=1, is=0; const int n=value.length(); const int nm1=n-1; int nnew=n; beginc=begin.cond(); endc=end.cond(); if(beginc==MGENDC_1D || beginc==MGENDC_2D) {nnew+=1;is=1;} else if(beginc==MGENDC_12D) {nnew+=2; is=2;} if(endc==MGENDC_1D || endc==MGENDC_2D){nnew+=1; ie=2;} else if(endc==MGENDC_12D) {nnew+=2; ie=3;} if(int(order)>nnew) order=nnew; const int ncd=value.sdim(); value_new=value; value_new.reshape(nnew,is); int nnewm1=nnew-1; for(j=0; jm2)?m1:m2; double* work2=new double[m]; int n; int error; blgcs_((const int*)ibc, begin_deriv, end_deriv, ncd, nv, point_kind, points.data(), ncir, idk, rcir, iv, irc, work1,work2, &n, &m_knot_vector(0), &m_line_bcoef(0,0), &error); delete[] work1; delete[] work2; delete[] idk; delete[] rcir; if(error==1){ error=0; //Return of BLGCS error=1 means normal. m_knot_vector.set_bdim(n); m_knot_vector.reshape(n+4); m_line_bcoef.set_length(n); m_line_bcoef.reshape(n); }{ //Generate polyline B-Rep. of order 2. //When error detected, the polyline that connects input points is set. m_knot_vector=MGKnotVector(2,points.length(),0.,1.); m_line_bcoef=points; } } //Construct MGLBRep that interpolates data points (tau(i), rlb.eval(tau(i))) // for 0<=i=3) cod11=0; cod12=cod11+1;if(cod12>=3) cod12=0; int com21=1; if(coordinate2<3){ cod21=kcod2;if(cod21>=3) cod21=0; if(cod21==coordinate1)com21=0; } //cod11,12,21 are 3D coordinate id of brep1 and 2. //com21 is id of 2nd line coordinate that is missing in 1st line. MGVector F,G(3); MGPosition b1,b2,p1,p2; int added; MGLBRep line; double tmid,s1,s2,diff; for(int loop=0; loop<3; loop++){ //Maximum loop counter is 3(3 times as much as output of BLUMIX) added=0; n=bp.length(); line=MGLBRep(endc_s,endc_e,tau,bp); for(i=1; ierror){ //brep1 differs from line, add point. G=brep2.closest_mix(coordinate2,coordinate1,s1,p1,F); bp.insert_at(i+1,G); tau.add_data(tmid); i+=1; n+=1; added+=1; } else{ if(coordinate2<3) b2=MGPosition(2,F,0,cod21); else b2=MGPosition(s1,F(coordinate1)); brep2.on(b2,s2); p2=brep2.eval(s2); diff=(p2-b2).len(); if(diff>error){ //brep2 differs from line, add point. G.set(cod11)=p1.ref(0); G.set(cod12)=p1.ref(1); G.set(coordinate1)=p2.ref(com21); bp.insert_at(i+1,G); tau.add_data(tmid); i+=1; n+=1; added+=1; } } } if(!added) break; } if(added){ n=bp.length(); line=MGLBRep(endc_s,endc_e,tau,bp); } (*this)=line; } //Function for BLUMIX constructor. Given 3D point F, //compute correct point of F that is closest to F. MGPosition MGLBRep::closest_mix( int coordinate2, //Missing coordinate kind of this(say 2nd line). //coordinate2 can be 3. int coordinate1, //Missing coordinate kind of P(say, of 1st line). //coordinate1 cannot be 3. double tau, //Parameter value of P, of 1st line, //used only when coordinate2=3. const MGPosition& P, //Point of 1st line(correct coordinates). const MGPosition& F //3D point, used to coose closest point to F //when more than one point are found. )const{ MGCParam_list list; int kcod; int com2=0, com21=1; if(coordinate2<3){ kcod=coordinate2+1; if(kcod>=3) kcod=0; if(kcod==coordinate1){com2=1; com21=0;} } int com1=com2+1; if(com1>=2) com1=0; //com2 is id of 2nd line coordinate that is common to P(1st line). //com21 is id of 2nd line coordinate that is missing in P(1st line). //com1 is id of P coordinate that is common to 2nd line. if(coordinate2==3) list=isect_1D(tau); else{ double data=P.ref(com1); list=isect_1D(data,com2); double tol=MGTolerance::wc_zero(); if(!list.entries()) list=isect_1D(data+tol,com2); if(!list.entries()) list=isect_1D(data-tol,com2); } kcod=coordinate1+1; if(kcod>=3) kcod=0; MGPosition Q(3,P,kcod); int n=list.entries(); if(!n){ Q(coordinate1)=F(coordinate1); return Q; } MGPosition A=eval(list.removeFirst()); Q(coordinate1)=A(com21); if(n==1) return Q; double dist=(Q-F).len(), dist2; MGPosition Q2(Q); for(int i=1; i0) //// mult>1 t=MGKnotVector(t,MGKnotArray(brk,mult)); } *this=MGLBRep(pp,t); } MGLBRep::MGLBRep( const MGLBRep& old_brep, //Original B-Rep. const MGKnotArray& knots //Knots to add. //Gets new B-Rep by adding knots to an original B-Rep. ):MGCurve(old_brep) ,m_knot_vector(old_brep.order(),old_brep.bdim()) ,m_line_bcoef(old_brep.bdim(),old_brep.sdim()) { update_mark(); const int k=old_brep.order(); const int n1=old_brep.bdim(); const int irc1=old_brep.m_line_bcoef.capacity(); const int ncd=m_line_bcoef.sdim(); const int nad=knots.length(); double* tad=new double[nad]; int* mlt=new int[nad]; int mlt_total=0; const MGKnotVector& t=old_brep.knot_vector(); int km1=k-1; for(int i=0; i=km1 && t[j1-1]==tadi){ j1--; mlt1++; }; } mlt2+=mlt1; if(mlt2>=k) mlt2=km1; mlt[i]=mlt2; mlt_total+=mlt[i]; } const int irc2=n1+mlt_total; m_knot_vector.reshape(irc2+k); m_line_bcoef.reshape(irc2); double* work=new double[k*k]; int n2; bluakt_( k, n1, old_brep.knot_data(), old_brep.coef_data(), irc1, ncd, nad, tad, mlt, irc2, work, &n2, &m_knot_vector(0), &m_line_bcoef(0,0)); m_knot_vector.set_bdim(n2); m_line_bcoef.set_length(n2); delete[] tad; delete[] mlt, delete[] work; } //Construct LBRep by connecting brep1 and brep2 to make one B-Representation. //brep1's parameter range will not be changed, instead brep2's range //will be so modified that brep2 has the same 1st derivative magnitude //as the original brep1's at the connecting point //(start or end point of brep1). //continuity and which can be obtained using the fucntion continuity(). MGLBRep::MGLBRep( const MGLBRep& brep1, //B-Rep 1. int continuity, //continuity. int which, //which point of brep1 to which of brep2. const MGLBRep& brep2 //B-Rep 2. ):MGCurve(brep1){ assert(0<=which && which<=3); *this=brep1; connect(continuity,which,brep2); } ///Gets new B-Rep by subdividing the original one into a part. ///New one is exactly the same as the original except that it is partial. ///id1 and id2 are id's of old_brep.knot_vector(), and indicates the parameter range ///of old_brep as from t[id1] to t[id2]. Here t=old_brep.knot_vector(). ///This constructor employs the partial knot vector of t and old_brep's B-coefficients. ///And so, knot multiplicity of start and end of the new knot vector is not guaranteed. ///It depends on the original one. MGLBRep::MGLBRep( int id1,///< start id of old_brep's knot vector. int id2,///< End id of old_brep's knot vector. const MGLBRep& old_brep ///=id2){ int idSave=id1; id1=id2; id2=idSave; } int k=old_brep.order(); int km1=k-1; if(id1n) id2=n; const MGKnotVector& t=old_brep.knot_vector(); const MGBPointSeq& bcoef=old_brep.line_bcoef(); while(id1=k && t[id2]==t[id2-1]){ id2--; } if(id1>=id2 || t[id1]>=t[id2]){ //The case of illegal input data. m_knot_vector=t; m_line_bcoef=bcoef; return; } int startID=id1-km1; int newBdim=id2-startID; m_knot_vector=MGKnotVector(startID,newBdim,t); m_line_bcoef=MGBPointSeq(startID,newBdim,bcoef); } //Gets new B-Rep by computing a part of the original. New one is exactly the same //as the original except that it is partial. MGLBRep::MGLBRep( double t1, double t2, //New parameter range. t1 must be less than t2. const MGLBRep& old_brep,//Original B-Rep. int multiple //Indicates if start and end knot multiplicities //are necessary. =0:unnecessary, !=0:necessary. //If multiple==true(!=0), knot(i)=t1 and knot(n+i)=t2 for i=0,..., k-1 will be //guaranteed. //Both t1 and t2 must be inside te range of old_brep. ):MGCurve(old_brep) ,m_knot_vector(old_brep.order(),old_brep.bdim()) ,m_line_bcoef(old_brep.bdim(),old_brep.sdim()) { const int ncd=old_brep.sdim(); if(t1>=t2){ double tm=(t1+t2)*.5; m_knot_vector.size_change(1,1);//order=1, brep dimension=1. m_line_bcoef.resize(1,ncd); m_knot_vector(0)=m_knot_vector(1)=tm; m_line_bcoef.store_at(0,old_brep.eval(tm)); return; } int i1=old_brep.m_knot_vector.locate(t1), i2=old_brep.m_knot_vector.locate(t2,1); double error=old_brep.m_knot_vector.param_error(); double ti1=old_brep.m_knot_vector[i1]; if((t1-ti1)<=error) t1=ti1; // else{ // double ti1p1=old_brep.m_knot_vector[i1+1]; // if((ti1p1-t1)<=error) t1=ti1p1; // } // double ti2=old_brep.m_knot_vector[i2]; // if((t2-ti2)<=error) t2=ti2; // else{ double ti2p1=old_brep.m_knot_vector[i2+1]; if((ti2p1-t2)<=error) t2=ti2p1; // } const int k=old_brep.order(); const int n1=old_brep.bdim(); const int irc1=old_brep.m_line_bcoef.capacity(); const int irc2=old_brep.bdim(); double* work=new double[k*k]; int n2; bluprt_(k, n1, old_brep.knot_data(), old_brep.coef_data(), irc1, ncd, t1, t2, irc2, work, &n2, &knot(0), &coef(0,0) ,multiple); m_knot_vector.set_bdim(n2); m_line_bcoef.set_length(n2); delete[] work;//std::cout<<(*this);/////////// } // Construct a Line B-Rep by changing space dimension and order of coordinate. MGLBRep::MGLBRep( int dim, // New space dimension. const MGLBRep& old_brep, // Original Line B-rep. int start1, // Destination order of new line. int start2 // Source order of original line. ):MGCurve(old_brep) ,m_knot_vector(old_brep.knot_vector()) ,m_line_bcoef(dim,old_brep.m_line_bcoef,start1,start2) { update_mark(); } // MGLBRep(const MGLBRep&); //Copy constructor. // We can use default copy constructor. //Destructor // ~MGLBRep(); //We can use default destructor. //This constructor constructs B-Rep, converting from PP-Rep. //Knot Vector is input. Each knot of the knot vector is break point of //pprep. The continuities at all the break points must be C(k-2) where //k is the order of pprep. MGLBRep::MGLBRep( const MGPPRep& pp, //PP-rep const MGKnotVector t //Knot Vector ):MGCurve(),m_knot_vector(t) ,m_line_bcoef(t.bdim(),pp.sdim()){ assert(t.order()==pp.order()); const int ncd=pp.sdim(); const int k=pp.order(); //order. const int ipc=pp.nbreak(); const int l=ipc-1;//Number of spans. int n=t.bdim(); const int ipcw=n+k-2; double* pcwork=new double[ipcw*k*ncd]; const int irc=m_line_bcoef.capacity(); blctpb_(pp.break_point_data(),pp.coef_data(),l,k,ncd,n, t.data(),ipc,ipcw,irc, pcwork, &m_line_bcoef(0,0)); delete[] pcwork; } ///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 MGLBRep::approximate_as_LBRep( MGLBRep& lb, ///