#include "MGCLStdAfx.h" #include "mg/Tolerance.h" #include "mg/Straight.h" #include "mg/Surface.h" #include "topo/Face.h" #include "Tl2/TL2parameter.h" #include "TL2/TL2LPline.h" #include "TL2/TL2Polyline.h" /****************************************************************/ /* Copyright (c) 2017 by System fugen G.K. */ /* All rights reserved. */ /****************************************************************/ ///mgTL2LPline is a proprietry class for Face tessellation. ///mgTL2LPline is limitted subinterval of mgTL2Polyline, ///holds the starting id of mgTL2Polyline, and the number of vertices. // enum polyline_type{ // WHOLE_INNER=0, //whole points are free inner points. // START_BOUNDARY, //only start point is connected to a boundary line. // END_BOUNDARY, //only end point is connected to a boundary line. // START_END_BOUNDARY,//Only start and end points are connected to a boundary. // //Inner points except start and end are not on a boundary. // WHOLE_BOUNDARY //All of the points are on a boundary. // }; //////////// constructor /////////////// ///Construct from subinterval of input lpline. mgTL2LPline::mgTL2LPline( const mgTL2LPline& lpline, int idS, //starting id of lpline int nV ):m_polyline(lpline.m_polyline),m_idS(lpline.m_idS),m_nV(lpline.m_nV){ limit(idS,nV); assert(m_idSbdim()); } void mgTL2LPline::setNull(){ m_polyline=0; m_idS=0; m_nV=0; } //Change m_polyline's id to this mgTL2LPline's id. //Function's return value is true if id_in is valid id for this mgTL2LPline. //False if not. bool mgTL2LPline::change_id( int id_in, //id of m_polyline. int& id_out //id of this will be output. )const{ if(m_nV>0){ if(id_in=m_nV) return false; }else{ if(id_in>m_idS) return false; id_out=m_idS-id_in; if(int(id_out)>=(-m_nV)) return false; } return true; } ///Construct new curve object by copying to newed area. ///User must delete this copied object by "delete". mgTL2LPline* mgTL2LPline::clone()const{ return new mgTL2LPline(*this); } //Evaluation of this with the normalized parameter value t from 0. to 1. //is provided. t=0. for the start point, t=1. for the end point. MGVector mgTL2LPline::eval(double t, int nderi)const{ assert(0.<=t && t<=1.); const mgTL2Polyline& pl=*(TL2Polyline()); const MGKnotVector& kv=pl.knot_vector(); double ts=kv(m_idS+1), te; if(m_nV>0){ te=kv(m_idS+m_nV); }else{ te=kv(m_idS+2+m_nV); } MGVector result=pl.eval(ts+(te-ts)*t,nderi); if(m_nV<0 && nderi%2) result.negate(); return result; } //Get id of m_Bpolylines of m_param of m_polyline from vertex id i. //Function's return value is //true if the point of t is a boundary point, false if not. bool mgTL2LPline::get_id_from_VertexID(int i, short id[3])const{ assert(i0) return m_polyline->get_id_from_VertexID(i+m_idS, id); return m_polyline->get_id_from_VertexID(m_idS-i, id); } //Get i-th point surface parameter (u,v) of this polyline. //i is relative one that start from 0 even for opposite direction. MGPosition mgTL2LPline::uv(int i)const{ assert(i0) return m_polyline->uv(i+m_idS); return m_polyline->uv(m_idS-i); } //Get i-th point(x,y,z,xn,yn,zn) of this polyline. //Here (x,y,z) is the position data, and (xn,yn,zn) is the unit normal at (x,y,z). //i is relative one that start from 0 even for opposite direction. MGPosition mgTL2LPline::xyz(int i, bool need_normal)const{ assert(i0) return m_polyline->xyz(i+m_idS,need_normal); return m_polyline->xyz(m_idS-i,need_normal); } //Update this by limiting the parameter range of the curve. ///Limitting is done at the knot parameter for both start and end. mgTL2LPline& mgTL2LPline::limit( int idS, //start point id of this mgTL2LPline. //idS is relative one that starts from 0 even for opposite direction. int nV //Number of vertices. ){ assert(nV<=number_of_points()); if(m_nV>0){ assert(idSbdim()); return *this; } //Obtain the mid point of this line. void mgTL2LPline::mid(MGPosition& uvmid){ int nmid=number_of_points()/2; uvmid=uv(nmid); } //Get the number of points of this polyline. int mgTL2LPline::number_of_points()const{ if(m_nV>0) return m_nV; return -m_nV; } //Reverse the direction. void mgTL2LPline::reverse(){ if(m_nV>0){ m_idS+=m_nV-1; m_nV=-m_nV; }else{ m_idS=int(m_idS+1+m_nV); m_nV=-m_nV; } assert(m_idSbdim()); } //Subdivide at the id. void mgTL2LPline::subdivide( int id, //Relative one that start from 0 even for opposite direction. mgTL2LPline& lp1, //devided 1st mgTL2LPline. mgTL2LPline& lp2 //devided 2nd mgTL2LPline. )const{ assert(m_nV>2 || m_nV<-2); lp1.m_polyline=lp2.m_polyline=m_polyline; lp1.m_idS=m_idS; if(m_nV>0){ assert(int(id)bdim()); } //Compute the intersections of sl and this mgTL2LPline. //Function's return value is the (nearest) intersection vertex id of lp if >=0. //If return value is minus, intersection not found. int mgTL2LPline::isectSlTl( const MGStraight& sl )const{ const mgTL2parameter& tlparam=TL2param(); const MGSurface& sufaceOrg=tlparam.get_surface(); double serror=sufaceOrg.parameter_error(); double errorSave=MGTolerance::set_wc_zero(serror); int id_lp=-1; const mgTL2Polyline* ipoly=TL2Polyline(); MGCCisect_list tlist=ipoly->isect(sl); if(!tlist.isEmpty()){ MGCCisect ti=tlist.front(); //change the parameter value to indicate a vetex point of the polygon. int id_poly=int(ti.param1()-ipoly->param_s()+.5); int id_lp2; if(change_id(id_poly,id_lp2)) id_lp=id_lp2; } MGTolerance::set_wc_zero(errorSave); return id_lp; } //Polygonize of the (u,v) space straight line from this->uv(id1V) to pline2.uv(id2V). //The direction of the output is from id1V to id2V. //polygonizeSL does ensure the deviation from the surface to be within the surface //tolerance. std::unique_ptr mgTL2LPline::polygonizeSL( const mgTL2LPline& pline2, int id1V, //id of this vertex. int id2V //id of pline2's vertex. )const{ MGPosition uvS=uv(id1V); MGPosition uvE=pline2.uv(id2V); MGStraight sl(uvE,uvS); std::unique_ptr uvpolyline(new mgTL2Polyline(TL2param(),sl)); short idS[3]; if(get_id_from_VertexID(id1V,idS)) uvpolyline->set_startID(idS); short idE[3]; if(pline2.get_id_from_VertexID(id2V,idE)) uvpolyline->set_endID(idE); return uvpolyline; } std::unique_ptr mgTL2LPline::getPolygonizedMidLine( const mgTL2LPline& lp2, int& id0, int& id2 )const{ id0=number_of_points()/2; MGPosition uvM=uv(id0); MGStraight slMid(uvM-uv(id0-1),uv(id0+1)-uvM,uvM); id2=lp2.isectSlTl(slMid); std::unique_ptr mid; if(id2>0) mid=polygonizeSL(lp2,id0,id2); return mid; } //Interpolate pline1.uv(id1V) and pline2.uv(id2V) //by a straight line for the tessellation. //The direction of the output is from id1V to id2V. //interpolateSL does not ensure the deviation from the surface. std::unique_ptr interpolateSL( const mgTL2LPline& pline1, const mgTL2LPline& pline2, int id1V, //id of pline[id1]'s vertex. int id2V //id of pline[id3]'s vertex. ){ std::unique_ptr uvpolyline =std::unique_ptr(new mgTL2Polyline(pline1.TL2param())); int nbd=2; MGBPointSeq& uvbp=uvpolyline->line_bcoef(); uvbp.resize(nbd,2); MGPosition uvS=pline1.uv(id1V),uvE=pline2.uv(id2V); uvbp.store_at(0,uvS); MGKnotVector& uvKnotv=uvpolyline->knot_vector(); uvKnotv.size_change(2,nbd); uvKnotv(0)=uvKnotv(1)=0.; double tnbdm1=1.; uvbp.store_at(1,uvE); uvKnotv(nbd+1)=uvKnotv(nbd)=tnbdm1; short idBP[3]; if(pline1.get_id_from_VertexID(id1V,idBP)) uvpolyline->set_startID(idBP); if(pline2.get_id_from_VertexID(id2V,idBP)) uvpolyline->set_endID(idBP); return uvpolyline; } ///Debug Function std::ostream& mgTL2LPline::out(std::ostream& ostrm)const{ ostrm<<"mgTL2LPline::"<