/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #ifndef _MGLoop_HH_ #define _MGLoop_HH_ #include "mg/Pvector.h" #include "topo/LSPoint_vector.h" #include "topo/Boundary.h" #include "topo/TrimLoop.h" class MGInterval; class MGPosition; class MGCurve; class MGStraight; class MGSurface; class MGLCisect_vector; class MGLLisect_vector; class MGPVertex; class MGLEPoint; class MGLPoint; class MGLoop; class MGEdge; class MGFSurface; class MGFace; /** @file */ /** @addtogroup TOPO * @{ */ // //Define MGLoop Class. ///MGLoop is a boundary of a face, a boundary of 2D manifold cell. ///MGLoop accepts parameter space curve and world space curve of ///of a boundary curve, and constructs a boundary of a face from the ///two types of curves. ///Input curves direction indicate which part of the face will be target ///part after trimed by the boundary. In 2D space (u,v) of the parameter ///space, LEFT side of the parameter curve along the curve's direction ///is the target part of face. class MG_DLL_DECLR MGLoop:public MGBoundary{ public: enum LoopKind{ UNDEFINED=-1, INACTIVE=0, PERIMITER_LOOP=1, OUTER_LOOP=2, ///& boundaries). ///Inside the outer boundary means that inside outer_boudary_param() or not. ///This must not be used for faces that do not have perimeter or outer boundary ///loop. ///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 MG_DLL_DECLR friend int inside_outer_loop( const MGPosition& uv, const std::vector& loop, const MGSurface* surf=0 ); /////////Constructor///////// ///Void constructor. MGLoop(); ///Construct a loop of one edge. explicit MGLoop(MGEdge* edge); ///Copy constructor. MGLoop(const MGLoop& loop2); ///Construct a Loop of one edge of one curve cell. ///param_curve is parameter space representation of the face ///of which this loop will be a boundary, will make parameter cell. ///world_curve is world coordinate representation of the face ///of which this loop will be a boundary, will make binder cell. ///range1 is parameter range of the curve param_curve, ///range2 is parameter range of the curve world_curve. ///When range1,2 are not specified, the start and the end of the curve are ///treated as their ranges. ///***param_curve and world_curve must have the same direction. MGLoop(const MGCurve& param_curve, const MGCurve& world_curve); MGLoop(const MGCurve& param_curve, const MGInterval& range1, const MGCurve& world_curve, const MGInterval& range2); MGLoop(std::unique_ptr& param_curve, std::unique_ptr& world_curve); /////////Destructor///////// ////////////Operator Overload//////////// ///Assignment. ///When the leaf object of this and bnd2 are not equal, this assignment ///does nothing. MGLoop& operator=(const MGGel& gel2); MGLoop& operator=(const MGLoop& gel2); ///Object transformation. MGLoop& operator+=(const MGVector& v); MGLoop& operator-=(const MGVector& v); MGLoop& operator*=(double scale); MGLoop& operator*=(const MGMatrix& mat); MGLoop& operator*=(const MGTransf& tr); ///This operator is to sort loops in the order: /// 1. Perimeter boundary. /// 2. Outer boundary. /// 3. Inner boundary. /// 4. Inactive loop. bool operator<(const MGLoop& gel2)const; bool operator<(const MGComplex& gel2)const; bool operator<(const MGGel& gel2)const; /////////Member Function///////// ///Test if this is active boundary. bool active() const; ///Append edge to the end of loop. ///"append" connects the edge's start to the end of the loop. void append(MGEdge* edge); ///Build one edge of srf from the curve wcrv on srf and common information ///pspan and peri_num, which are a perimeter peri_num's parameter spans(psapn). ///wcrv must not be a MGCompositeCurve. ///One edge is generated and append to this loop. void append_edge_from_crv( const MGSurface& srf,///& pspan,/// ranges2[2*i+1]. /// Let f1() be this loop, and f2() be loop2, then /// f1(ranges1[j]) and f2(ranges2[j]) represent the same point in star /// Face world for 0<=j& pranges1, std::vector& branges1, std::vector& pranges2, std::vector& branges2 )const; ///Compute curvilinear integral of the loop. ///Computation is done in the parameter space of the face. double compute_area()const; ///Copy loop data into this. ///This boundary data is cleared and loop's boundary is copied into this. void copy_boundary(const MGBoundary& loop); ///Copy boundary data into this, but does not copy the binders. void copy_boundary_without_binders(const MGBoundary& loop); ///Obtain vector of curves(TrimmedCurve) of the loop. ///The curves are of parameter space expression. ///Let crvs be the output of curves() and wcrvs of curves_world(), ///then crvs[i] corresponds to wcrvs[i] one by one. MGPvector curves()const; ///Obtain vector of curves(world coordinate expression) of the loop. ///Output curves are MGTrimmedCurve of edge's binders. ///When some of the edges do not have binders, they will be created. ///Let crvs be the output of curves() and wcrvs of curves_world(), ///then crvs[i] corresponds to wcrvs[i] one by one. MGPvector curves_world()const; ///Return i-th edge pointer. MGEdge* edge(int i); const MGEdge* edge(int i) const; ///Test if at least one edge is included in this loop. bool edge_exist() const{return pcell_exist();}; ///Get edge number in this loop. ///If e is not a member of this loop, 0 will be returned. int edge_num(const MGEdge* e)const; ///Return end point of this loop as MGPosition. ///The point is of parameter space. MGPosition end_point() const; ///Return end point of this loop as MGLEPoint. ///loop must include at least one edge, or this output is undefined. MGLEPoint end_LPoint() const; ///Get error of this loop. ///This is obtained from the parent surface. If parent surface did not /// exist, error=the box of the loop by relative zero. double error()const; ///Evaluation of the loop at the point t. MGVector eval(const MGLPoint& t, int nderi=0)const; ///Evaluation of the loop at i-th edge's parameter t. MGVector eval(int i, double t, int nderi=0)const; ///Return pointer of the face. If the loop is not a boundary of any face, ///null will be returned. const MGFace* face() const; MGFace* face(); ///Return pointer of the first edge. const MGEdge* first_edge() const; MGEdge* first_edge(); ///Get the loop id of this loop in the star face baoundary. ///Let face=face(), then face->loop(get_loop_id_in_face())=this; ///When this does not have star face, or this is not a boundary of a face, ///-1 will be returned. int get_loop_id_in_face()const; ///Test if parameter value (u,v) is inside this loop or not. ///inside means inside face, that is, ///if the loop is inner, outside inner loops and ///if the loop is outer boundary loop, inside the outer boundary loop. ///This can be used for perimeter boundary loops. ///Returned is: /// 0:outside(not on the loop) /// 1:unknown /// 2:inside(not on the loop) /// otherwise:on the loop(int(parameter edge id +100))will be returned. int inside(double u, double v) const; int inside(const MGPosition& uv) const; ///Return Object's type ID (TID) long identify_type()const; ///Compute intersections of this loop(parameter rep of a face) ///and param_curve. MGLCisect_vector isect(const MGCurve& param_curve) const; ///Compute intersections of this loop(parameter rep of a face) ///and param_curve. MGLCisect_vector isect( double error,//error to get intersection of the loops and sl. const MGCurve& param_curve ) const; ///Compute intersection points of 1D sub curves of the original loop. ///Parameter values of intersection points(MGLEPoint's) will be returned. std::vector isect_1D( double f, ///< Coordinate value int coordinate=0 ///< Coordinate kind of the data f(from 0). ) const; ///Compute intersections of this loop(parameter rep of the face) ///and param_curve. ///isect_with_endpoints() includes endpoints of both if they are close enough ///(within tolerance). MGLCisect_vector isect_with_endpoints (const MGCurve& param_curve) const; ///Test if this loop is inactive or not. bool is_inactive(const MGFSurface* srf=0) const; ///Test if this loop is inner boundary. ///Inner boundary is: /// (1) closed loop. (2) the direction is clockwise. bool is_inner_boundary(const MGFSurface* srf=0) const; ///Test if this loop is outer boundary. ///outer boundary is: /// (1) closed loop. (2) the direction is anti-clockwise. bool is_outer_boundary(const MGFSurface* srf=0) const; ///Test if this loop is perimeter boundary. ///Perimeter boundary is: /// both ends are on the surface perimeter. bool is_perimeter_boundary(const MGFSurface* srf=0) const; ///Test if this loop is network. bool is_network(const MGFSurface* srf=0) const{return m_kind==NETWORK;}; ///Compute intersections of two loops. MGLLisect_vector isect(const MGLoop& loop2)const; ///Join two loops. ///start indicates which end of this loop loop2 should be connected to. ///start=true: connect start of this and loop2's end. ///start=false: connect end of this and loop2's start. ///The 2nd form takes the ownership of loop2, will delete loop2. void join(bool start, const MGLoop& loop2); void join(bool start, MGLoop* loop2); void join(bool start, std::unique_ptr& loop2); ///Join adjacent two C1 continuous edges to one edge. ///When the number of edges is equal to or less than 4, join is not executed. void join_C1_edges( int parameter_normalization=2 ///Specify how rebuilt edes's parameterization be done. //=0: no parameter normalization. //=1: normalize to range=(n, n+1) for the n-th edge. //=2: normalize to make the average length of the 1st derivative // is as equal to 1. as possible. Let the n-th edge's parameter range // is (TSn, TEn), then, TSn=TEn-1. ); ///Return edge pointer of the last edge. const MGEdge* last_edge() const; MGEdge* last_edge(); ///Make this loop as closed. ///This loop's 1st edge's start point must be the same as the last edge's end point. ///However, this is not tested in make_close. void make_close(); ///Make a vertex at lp and subdivide the edge into two edges. ///Returned is true if subdivision is done and false if no subdivision ///is done since lp was one of existed vertex. ///When function's return value is true, pre is always the same edge as ///lp's edge and the iterator is unchanged. bool make_vertex( const MGLEPoint& lp,/// subdivide( const std::vector& ranges ); ///Subdivide this loop so that one parameter range from le1 to le2 becomes one edge. ///le1, and 2 must be of the same edge. ///new edge between le1 and le2 will be output. MGEdge* subdivide( MGLEPoint& le1, MGLEPoint& le2 ); ///Trim the loop. Result loop is from t1 to t2; ///The loop can be closed one. In this case, t1 can be >t2. ///When not closed, t1 must be less than t2. void trim(const MGLEPoint& t1, const MGLEPoint& t2); ///Trim the loop. Result is from start to t1. void trim_end(const MGLEPoint& t1); ///Trim the loop. Result is from t1 to end. void trim_start(const MGLEPoint& t1); protected: ///Fundamental constructor. ///Construct from boundary complex(i.e. MGLoop). ///This constructor takes the ownership of MGCell* in boundary. MGLoop( std::list boundaries ///0. means inside of this closed loop is active(outer boundary). ///& crvs,/// isect_1D_tess( double f, ///< Coordinate value int coordinate=0 ///< Coordinate kind of the data f(from 0). ) const; ///Compute intersections of this loop's binder edges with face. ///If some parameter edges did not have a binder, isect_binder generates them. MGLSPoint_vector isect_binder(const MGFSurface& face) const; ///Make loop void make_loop(std::unique_ptr& param_curve, std::unique_ptr& world_curve); ///Make a vertex at lp and subdivide the edge into two edges. ///Returned is true if subdivision is done and false if no subdivision ///is done since lp was one of existed vertex. ///When function's return value is true, pre is always the same edge as ///lp's edge and the iterator is unchanged. bool makeVertexWithLcis( const MGLEPoint& lp,///& pcurves,///<(u,v) 2D parameter curves of surf. MGPvector& networks /// trim_out_subloop(const MGLEPoint& ts, const MGLEPoint& te); /** @} */ // end of TOPO group #endif