/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #ifndef _MGFace_HH_ #define _MGFace_HH_ #include #include "mg/Default.h" #include "mg/drawParam.h" #include "mg/BPointSeq.h" #include "mg/Unit_vector.h" #include "mg/Position.h" #include "mg/Curve.h" #include "mg/Surface.h" #include "mg/FSurface.h" #include "mg/Pvector.h" #include "topo/Cell.h" #include "topo/LEPoint.h" #include "topo/FOuterCurve.h" class MGSSisect_list; class MGCSisect_list; class MGPosition_list; class MGLBRep; class MGCellNB; class MGLoop; class MGLEPoint; class MGShell; class MGFSurface; class MGHHisect_vector; // //Define MGFace Class. /** @addtogroup TOPO * @{ */ typedef std::vector SHLL_COM_EDGES;//Used for tessellatiion(shade). //Represents n polylines of n edges of a loop. //SHLL_COM_EDGES[j] is j-th edge's polyline of a loop. //Generally a face has multiple SHLL_COM_EDGES. ///MGFace is a trimmed surface. ///MGFace is an instance of MGCell, can be a constituent of MGShell. ///Many useful functions are provided in MGFSurface. See MGFSurface. class MG_DLL_DECLR MGFace: public MGCell, public MGFSurface{ public: ///Faceのスケーリングを行い,Faceを作成する。 ///Scaling of the Face by a double. MG_DLL_DECLR friend MGFace operator* (double s, const MGFace& face); ///////// Constructor ///////// ///Null face. MGFace():MGCell(){;} ///Copy constructor. MGFace(const MGFace& face); ///Constructor. MGFace(const MGFace& face, bool copy_boundary, bool no_binder=false); ///Fundamental constructor. ///Construct a face from geometry of manifold dimension 2 ///and the boundaries. ///The constructor takes the ownership of geo and MGBoundary in boundaries. ///boundaries must be loops. MGFace( MGSurface* geo, std::vector& boundaries, MGCell* binder ); ///Face of whole surface of no boundary. MGFace(const MGSurface& surf) :MGCell(surf),m_box_param(surf.param_range()) {;} ///Conversion constructor from MGFSurface to MGFace. MGFace(const MGFSurface& surf); ///Face of whole surface of no boundary. ///Ownership of surf is transfered to the face. ///(that is surf must be a newed object.) MGFace(MGSurface* surf) :MGCell(surf),m_box_param(surf->param_range()) {;} ///Construct a face by copying boundaries(only parameter rep of the boundary) ///from argument boundaries. ///Second form is to input a newed surface. The constructor takes the ownership ///of the surf. MGFace(const MGSurface& surf, const std::vector& boundaries); MGFace(MGSurface* surf, const std::vector& boundaries); ///////// operator overload///////// ///Assignment. ///When the leaf object of this and cell2 are not equal, this assignment ///does nothing. MGFace& operator=(const MGGel& gel2); MGFace& operator=(const MGFace& gel2); /// Faceに平行移動を行ないオブジェクトを生成する。 ///Translation of the Face MGFace operator+ (const MGVector& v) const; /// Faceに逆方向の平行移動を行ないオブジェクトを生成する。 ///Translation of the Face MGFace operator- (const MGVector& v) const; ///Faceのスケーリングを行い,Faceを作成する。 ///Scaling of the Face by a double. MGFace operator* (double s) const; /// 与えられた変換でFaceの変換を行い,Faceを作成する。 ///Transformation of the Face by a matrix. MGFace operator* (const MGMatrix& mat) const; /// 与えられた変換によってトランスフォームをおこないFaceを生成する。 ///Transformation of the Face by a MGTransf. MGFace operator* (const MGTransf& tr) const; ///Complexのスケーリングを行い,Complexを作成する。 ///Scaling of the Complex by a double. MGFace operator/ (double s) const{return (*this)*(1./s);}; ///Comparison of two curves. bool operator<(const MGFace& gel2)const{return is_less_than(gel2);}; bool operator<(const MGGel& gel2)const; ///PD144=MGFace. Output to PD144(Trimmed surface). int out_to_IGES( MGIgesOfstream& igesfile, int SubordinateEntitySwitch=0 )const; ///Debug Function std::ostream& out(std::ostream& ostrm) const; /// Output virtual function. std::ostream& outFS(std::ostream& ostrm) const{return out(ostrm);}; /////////Member function///////// ///Add a new loop to this face as aboundary. ///When the old loops that are outside the nloop will be removed from this. ///nloop can be inner or outer. void add_boundary(MGLoop* nloop); ///Generate arrow data of the tangent along u and v and the normal ///at the parameter value (u,v) of the surface. ///data[0] is the origin of the u-tangent arrow, data[1] is the top of the u-tangent arrow, ///data[2], [3] are two bottoms of u-tangent arrowhead. ///data[0], [4], [5], [6] are the points of v-tangent arrow. ///data[0], [7], [8], [9] are the points of v-tangent arrow. void arrow(double u,double v, MGPosition data[10])const; void arrow(const MGPosition& uv, MGPosition data[10])const{ arrow(uv[0],uv[1],data); } ///Append new one boundary to boundary vectors. ///Returned is the number of boudaries after appending. ///bound must be a newed MGLoop, and the ownership is transfered to this. ///*** append_boundary does not check validity with other loops ///(e.x. already existed loops will be outside the new boudanry bound). ///If the validity check is necessary, use add_boudanry(). int append_boundary(MGBoundary* bound); ///Obtain binder face pointer. ///Null when this does not have binder. MGFace* binder_face() const; ///Obtain all the boundary curves(world coordinates representation) ///of the face. ///That is, all of the outer boundaries and all of the inner boundaries. MGPvector face_boundaries()const; ///Return box of the parameter space of the face. ///After trimmed one. const MGBox& box_param() const; ///Return box of the parameter space of the FSurface. ///After trimmed one. const MGBox box_param2() const{return box_param();}; ///Build a loop of this face, given a closed curve crv on this face. Although crv ///is generally a MGCompositeCurve, this may be not the case. Returned MGLoop is not ///added into this face as a boundary. User must add it after the direction is adjusted. ///That is, the output loop can be an outer or inner loop. std::unique_ptr build_loop( const MGCurve& crv ///& trisVec )const; ///Test if directions of parameter curve and world curve of the face boundary ///is equal or not. This function can be used to test the pair of ///the output of outer_boundary() and outer_boundary_param(), or the pair of ///inner_boundary() and inner_boundary_param(). ///Return is: ///true if equal direction, false if opposite direction. bool equal_direction( const MGPvector& wcurves, ///& pcurves, ///& loops)const; ///Extract sub face that is bounded by networks loops. ///Extracted sub face is the smallest closed part of this face bounded by ///the networks that includes the parameter position uv(u,v). void extract_sub_face( const MGPvector& networks,///<(u,v) representation networks. const MGPosition& uv,///& face/// get_inner_boundary_loops(const MGBox& uvbox) const; ///Judge if the display list for vmode is made or not. //bool displayList_is_made(MGCL::VIEWMODE vmode)const; ///get face pointer if this is MGFace, else null will be returned. MGFace* get_face_pointer(){return this;}; const MGFace* get_face_pointer()const{return this;}; ///get surface pointer. Null will never be returned if this is valid MGFSurface. ///That is, if this is MGFace, base surface will be returned. MGSurface* get_surface_pointer(){return surface();}; const MGSurface* get_surface_pointer()const{return surface();}; ///Get number of inner boundaries as the output of the function. int get_number_of_boundaries()const{return number_of_boundaries();}; ///Test if this and 2nd object has common area about their box(), ///taking error into account. bool has_commonFS(const MGObject& obj2)const{return has_common(obj2);}; ///Test if this face has boundary loops or not in the specified box. ///If this has one, return true. bool hasLoop(const MGBox& uvbox)const; ///Test if this face has an inactive loop. ///If this has one, return true. bool hasInactiveLoop()const; ///Test if this face has the outer boundary loop instead of perimeter boundary ///loops. If this has the outer boundary loop and has not perimeter boundary loops, ///return true. bool hasOuterBoundaryLoop()const; ///Test if this face has perimeter boundary loops or not. ///If this has one, return true. bool hasPerimeterBoundaryLoop() const; ///Obtain i-th inner_boundary curves(world coordinates representation) ///of the face. Let the output of inner_boundary(i) be wcurves and ///of inner_boundary_param(i) be pcurves, then wcurves[j] corresponds ///to pcurves[j] one to one. Number of inner_boundary can be obtained ///by the function number_of_inner_boundary(). MGPvector inner_boundary(int i)const; ///Obtain i-th inner_boundary curves(world coordinates representation) ///of the face. Let the output of inner_boundary(i) be wcurves and ///of inner_boundary_param(i) be pcurves, then wcurves[j] corresponds ///to pcurves[j] one to one. Number of inner_boundary can be obtained ///by the function number_of_inner_boundary(). MGPvector inner_boundary_param(int i)const; ///Return Object's type ID (TID) long identify_type()const; ///Test if parameter value (u,v) is in the range of the face parameter. bool in_range(double u, double v)const; bool in_range(const MGPosition& uv)const; ///Test if (u,v) is inside the face. ///Function's return value is: /// 0:outside the face. /// 1:unknown. /// 2:inside the face, not on a boundary. /// <0:(u,v) is on an inner boundary, and abs(return code) is the loop id. /// 4:(u,v) is on the outer boundary. /// >=10: (u,v) is on a perimeter, (10+perimeter number) will be returned. int in_range_with_on(const MGPosition& uv)const; ///Compute the intersections of two objects. ///Intersections are obtained from two objects, which are known using ///the MGisects::object1() and object2(). ///****NOTE**** ///When two objects' manifold dimension are the same, object1 is this object ///at the invocation of MGObject::intersection(), and object2 is the argument ///object. ///However, their manifold dimension are not the same, object1 is always ///the lower dimension's object and object2 is the higer dimension's object. MGisects intersection(const MGObject& obj2)const; MGisects intersection(const MGCurve& obj2)const; MGisects intersection(const MGFSurface& obj2)const; MGisects intersection(const MGSurface& obj2)const; MGisects intersection(const MGFace& obj2)const; MGisects intersection(const MGShell& obj2)const; ///Intersection. MGCSisect_list isect(const MGCurve& curv) const; MGSSisect_list isect(const MGFSurface& fsurf) const; MGSSisect_list isect(const MGFace& fsurf) const; MGSSisect_list isect(const MGSurface& fsurf) const; MGHHisect_vector isect(const MGShell& shell2) const; ///Access to i-th element of u knot double knot_u(int i) const{return surface()->knot_u(i);}; ///Access to i-th element of v knot double knot_v(int i) const{return surface()->knot_v(i);}; ///Returns the u knot vector. const MGKnotVector& knot_vector_u()const{return surface()->knot_vector_u();}; MGKnotVector& knot_vector_u(){return surface()->knot_vector_u();}; ///Returns the v knot vector. const MGKnotVector& knot_vector_v()const{return surface()->knot_vector_v();}; MGKnotVector& knot_vector_v(){return surface()->knot_vector_v();}; ///Obtain i-th boundary loop of the face. MGLoop* loop(int i); MGLoop* loop(iterator i); const MGLoop* loop(int i)const; const MGLoop* loop(const_iterator i)const; ///Make a binder cell of this parameter cell. ///Returned is the binder pointer generated by new. ///The binder has no geometry, only has binder and parameter cell relationship. MGCellNB* make_binder() const; ///This is a newed MGFace or MGSurface object. ///If this is a MGFace, returns this pointer. ///If this is a MGSurface, construct a newed MGFace using this newed MGSurface, ///and returns the MGFace*. MGFace* make_face(){return this;}; ///Make outer boundary if not existed. void make_outer_boundary(); ///Get manifold dimension. int manifold_dimension() const{return 2;}; ///Obtain the i-th member partner face. const MGFace* member_partner_face(int i)const; ///Negate the face. void negate(); void negateFS(){negate();}; ///Compute normal vector(not unit) at uv. MGVector normal(const MGPosition& uv) const { return surface()->normal(uv.ref(0), uv.ref(1));}; ///Compute normal vector(not unit) at (u,v). MGVector normal(double u,double v) const { return surface()->normal(u, v);}; ///Test if no outer boundary except the surface perimeters. ///That is, test if the following two conditions are satisfied: /// 1. no perimeter boundaries. /// 2. no outer boundary. bool no_outer_boundaries()const; ///Get number of inner boundaries as the output of the function. int number_of_inner_boundaries()const { int dummy; return number_of_inner_boundaries(dummy);} ///Get number of inner boundary loops. ///Returned i is the id of the first inner boundary loop if inner boundaries ///exist. int number_of_inner_boundaries(int& i)const; ///Compute number of active loops. int number_of_loops()const; ///Get number of perimeter boundary loop. int number_of_perimeter_boundaries()const; ///Return MGObject pointer if this MGGel is an MGObject, else return null. MGObject* object_pointer(){return object();}; const MGObject* object_pointer()const{return object();}; ///Offset. ///distance is plus value if the direction is toward normal vector of the ///face. Minus if against the normal vector. ///エラーコード 0:成功 -1:曲率半径以上のオフセット不可 -3:面生成コンストラクタエラー MGFace offset(double distance, int& error)const; ///Offset. ///distance is plus value if the direction is toward normal vector of the ///face. Minus if against the normal vector. ///エラーコード 0:成功 -1:曲率半径以上のオフセット不可 -3:面生成コンストラクタエラー int offset(double distance, MGPvector& vecOfsFace)const; ///Offset. ///distance is plus value if the direction is toward normal vector of the ///FSurface. Minus if against the normal vector. ///エラーコード 0:成功 -1:曲率半径以上のオフセット不可 -3:面生成コンストラクタエラー int offset_fs(double distance, MGPvector& vecOfsFSurface)const; ///Test if a point P is on the face. ///Returned is true if the point P is on the face. ///false(0) if P was not on the face. bool on( const MGPosition& P,/// outer_boundary()const; ///Obtain boundary curves(parameter space representation) of the face. ///Let the output of boundary() be wcurves and of boundary_parameter() ///be pcurves, then wcurves[i] corresponds to pcurves[i] one to one. MGPvector outer_boundary_param()const; ///Obtain parameter value of the face whose world coordinates are P. MGPosition param(const MGPosition& P)const; ///Obtain parameter curves. ///In the case of surface, parameter curve is only one. However, in the case ///of face, number of parameter curves are more than one. MGPvector parameter_curves( int is_u, /// PBloop_curves() const; ///Return the foot of the perpendicular straight line from P. ///Computation is done from the guess parameter value. ///Function's return value is whether point is obtained(true) or not(false). bool perp_guess( const MGPosition& P, /// rebuild( int how_rebuild=1, ///=4 is recomended. ///MGTolerance::angle_zero(). void scalePolar( double angleBase, ///& surfaces///& networks,///& faces///& networks,///& faces///unit_normal(uv.ref(0), uv.ref(1));}; ///Compute unit normal vector at (u,v). MGUnit_vector unit_normal(double u,double v) const { return surface()->unit_normal(u, v);}; std::string whoami()const{return "Face";}; protected: ///Write Object's Member Data void WriteMembers(MGOfstream& buf) const; ///Read Object's member data. void ReadMembers(MGIfstream& buf); private: mutable MGBox m_box_param;///coef_sdim();}; ///compute box of the cell in m_box. ///Currently this does not compute corrct box, compute m_extent box. void compute_box() const; ///Compute parameter range box. void compute_box_param() const; ///Copy and set the binder face. void copy_binder(const MGFace& faceOriginal); ///Define curve division number when a curve crv be projected onto this MGFSurface. ///The result is used in prj2GetParamRange(). int get_proj_divnum(const MGCurve& crv)const; ///set box as null(to set the box as initial) void set_box_as_null()const; ///Test if (u,v) is inside inner boundary. inside means not on the ///boundary and not included inside the face. ///If true is returned, the id of m_boundaies is returned. ///Function's return value is: /// 0:outside of all the inner loops(not on the loop) /// 1:unknown /// 2:inside an inner loop(not on the loop), and the loop id is returned in id. /// otherwise:on the loop(int(MGEdge* of parameter edge))will be returned, /// and the loop id is returned in id. int inside_inner_boundary(const MGPosition& uv, int& id)const; ///Test if (u,v) is inside the outer boundary. ///Inside the outer boundary means that inside outer_boudary_param() or not. ///***Caution*** ///(1)This must not be used for faces that do not have perimeter or outer boundary ///loop. ///(2)inside_outer_boundary does not check about the inner loops. /// ///Function's return value is: /// 0:outside the outer boundary(not on a loop) /// 1:unknown /// 2:inside the outer boundary(not on a loop) /// otherwise:on the outer boundary loop int inside_outer_boundary( const MGPosition& uv )const; ///Intersection with MGFSurface. MGSSisect_list intersect(const MGFSurface& face2)const; ///Compute intersection points of an inner parameter line of this face and f2. ///The intersection point is used to compute surface to surface intersection lines. ///Function's return value is at most one intersection point in uvuv_list. ///One member of uvuv_list is (u1,v1,u2,v2), where (u1,v1) is a parameter of ///this surface and (u2,v2) is a parameter of surf. MGPosition_list intersectInner( const MGFace& f2 ///isect_area_length();}; ///Compute intersection points of this face's boundary(outer and inners) with ///face2. If intersection points are found and the boundary is a loop, ///the point's edge pointer(of this) will be stored in a member uvuv of uvuvs. ///uvuv[7] is the edge pointer. If the boundary is not a loop(that is, a perimeter of ///Surfaces), uvuv.sdim()==7 and an edge pointer is not returned. ///When uvuv.sdim()==8, the edge pointer of uvuv[7] is accessed through union mgEdgeP. ///uvuvs[i] is i-th intersection points. int isect_boundary( const MGFSurface& face2, MGPosition_list& uvuvs, /// isect1D_with_boundaries( double x, /// outer_curve() const; ///Obtain perimeter i's parameter range. ///Let rvec be std::vector of the fucntion's output, ///then rvec[j] is j-th parameter range of i-th perimeter. std::vector perimeter_param_range(int i) const; ///Dedicated function of range. ///Will check if point (u,v) is inside inner boundary or not. ///If inside an inner boundary, obtain the closest point to the boundary. MGPosition range_check_inner_boundary(const MGPosition& uv) const; ///Remove parameter uv from uvs that is outside face parameter range. void remove_outside_param(MGPosition_list& uvs)const; ///Shade the object in world coordinates. void shade( mgVBO& vbo,///* polylines,///& vecCrv ///& curves ///