/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #ifndef _MGCurve_HH_ #define _MGCurve_HH_ #include #include #include "mg/MGCL.h" #include "mg/Default.h" #include "mg/Position.h" #include "mg/Geometry.h" #include "mg/FSurface.h" #include "mg/Pvector.h" #include "mg/KnotVector.h" #include "mg/CCisect_list.h" #include "mg/CSisect_list.h" // //Define MGCurve Class. class MGInterval; class MGBox; class MGVector; class MGUnit_vector; class MGPosition_list; class MGTransf; class MGCParam_list; class MGPoint; class MGStraight; class MGEllipse; class MGLBRep; class MGRLBRep; class MGSurfCurve; class MGBSumCurve; class MGTrimmedCurve; class MGCompositeCurve; class MGSurface; class MGPlane; class MGSphere; class MGCylinder; class MGSBRep; class MGRSBRep; class MGBSumSurf; class MGCCisect_list; class MGCSisect_list; class MGIfstream; class MGOfstream; class MGFace; class MGShell; class MGCFisect_vector; class MGPPRep; class MGCommonON; class mgVBO; /** @file */ /** @addtogroup GEO * @{ */ ///MGCurve is an abstract class which represents a whole curve. class MG_DLL_DECLR MGCurve:public MGGeometry{ public: //////////////Constructor/////////////// ///Void constructor(初期化なしでオブジェクトを作成する。). MGCurve(); ///Copy constructor. MGCurve(const MGCurve& curve); /// Virtual Destructor. virtual ~MGCurve(); //////////// Operator overload(演算子多重定義) //////////// ///Assignment. ///When the leaf object of this and geo2 are not equal, this assignment ///does nothing. virtual MGCurve& operator=(const MGCurve& gel2){MGGeometry::operator=(gel2);return *this;}; ////////////Logical operator overload///////// ///Object transformation. virtual MGCurve& operator+=(const MGVector& v)=0; virtual MGCurve& operator-=(const MGVector& v)=0; virtual MGCurve& operator*=(double scale)=0; virtual MGCurve& operator*=(const MGMatrix& mat)=0; virtual MGCurve& operator*=(const MGTransf& tr)=0; ///Comparison. virtual bool operator==(const MGCompositeCurve& crv)const; virtual bool operator==(const MGTrimmedCurve& crv)const; virtual bool operator==(const MGGel& gel2)const=0; virtual bool operator<(const MGGel& gel2)const=0; //////////// Member Function //////////// ///Approximate this curve as a MGLBRep. ///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. virtual void approximate_as_LBRep( MGLBRep& lb,///offset_div_num(interval);}; ///@endcond ///Obtain ceter coordinate of the geometry. virtual MGPosition center() const; ///Obtain ceter parameter value of the geometry. virtual MGPosition center_param() const; ///Changing this object's space dimension. virtual MGCurve& change_dimension( int sdim, ///< new space dimension int start1=0, ///< Destination order of new object. int start2=0 ///< Source order of this object. )=0; ///Change parameter range. ///Be able to change the direction by providing t1 greater than t2. virtual void change_range( double t1, ///& vecComSpan ( /O) 共通部分のパラメータ範囲 /// 4nの配列で、vecComSpan(4*i+0),vecComSpan(4*i+1)が自身のパラメータ範囲 /// (vecComSpan(4*i+0) < vecComSpan(4*i+1))、 /// vecComSpan(4*i+2),vecComSpan(4*i+3)がcurve2のパラメータ範囲 /// MGCCisect_list& isect ( /O) 交点 ///戻り値: /// 3:交点も共通部分も求まった /// 2:交点のみが求まった /// 1:共通部分のみが求まった /// 0:交点も共通部分もなかった /// -1:共通エッジの収束計算エラー /// -2:共通エッジが4個以上求まった(のっていないと見なす) ///追記: /// 曲線が共通かどうかの誤差にはline_zero()、をパラメータ範囲の収束計算の /// 誤差には、パラメータ範囲*rc_zero()を使用する。 virtual int common( const MGCurve& curve2, std::vector& vecComSpan, MGCCisect_list& isect ) const; ///Test if this has a common line part with the 2nd curve. ///関数名:common ///目的:与えられた曲線と自身の共通部分があるかどうか調べる。 ///引数: /// const MGCurve& curve2, (I/ ) 与えられる曲線 /// std::vector& vecComSpan ( /O) 共通部分のパラメータ範囲 /// 4nの配列で、vecComSpan(4*i+0),vecComSpan(4*i+1)が自身のパラメータ範囲 /// (vecComSpan(4*i+0) < vecComSpan(4*i+1))、 /// vecComSpan(4*i+2),vecComSpan(4*i+3)がcurve2のパラメータ範囲 ///戻り値: /// 共通部分の数: 共通部分が求まった /// 0: 共通部分がなかった /// -1: 共通エッジの収束計算エラー /// -2: 共通エッジが4個以上求まった(のっていないと見なす) ///追記: /// 曲線が共通かどうかの誤差にはline_zero()を、パラメータ範囲の収束計算の誤差には、 /// パラメータ範囲*rc_zero()を使用する。 virtual int common( const MGCurve& curve2, std::vector& vecComSpan ) const; ///Exchange ordering of the coordinates. ///Exchange coordinates (i) and (j). virtual MGCurve& coordinate_exchange(int i, int j)=0; ///copy as a newed curve. ///The new curve will be MGLBRep or MGRLBRep. ///When original curve was a MGRLBRep, the new curve will be a MGRLBRep. ///Otherwise, the new curve will be a MGLBRep. ///Returned object must be deleted. virtual MGCurve* copy_as_nurbs() const=0; ///Convert this curve to Bezier curve. ///If this is MGLBRep or MGStraight, the shape is exactly the same ///as the original. Otherwise, this is apporoximated by MGLBRep. virtual void convert_to_Bezier(MGLBRep& bezier)const; ///Construct new curve object by changing the original object's space dimension. ///Returned is a newed object, ///user must delete this copied object by "delete". virtual MGCurve* copy_change_dimension( int sdim, ///< new space dimension int start1=0, ///< Destination order of new line. int start2=0 ///< Source order of this line. )const=0; ///Construct new curve object limitting the parameter range to prange. ///Construct new curve object by copying to newed area, ///and limitting the parameter range to prange. ///Returned is a newed object and must be deleted. virtual MGCurve* copy_limitted(const MGInterval& prange) const; ///Return curvature at the given point. ///When the curve is 2D, curvature has sign. when 3D, curvature is ///always plus. /// 与えられた点における曲線の曲率を返却する。 virtual double curvature( double ) const; ///Return curve pointer if this MGGel is an MGCurve, else return null. MGCurve* curve(){return this;}; const MGCurve* curve()const{return this;}; ///Compute curvilinear integral of the 1st two coordinates. ///線積分を求める。 ///This integral can be used to compute area sorounded by the curve. ///Second form is from param_s() to param_e(); ///curvilinear_integral from t1 to t2 can be obtained by ///Integral of (x*dy-y*dx) about t, where curve is expressed by ///f(t)=(x(t),y(t)), dx=dx/dt, and dy=dy/dt. virtual double curvilinear_integral(double t1, double t2) const; virtual double curvilinear_integral() const{ return curvilinear_integral(param_s(), param_e()); }; ///Compute mean length of 1st derivative vector. virtual double deriv_length()const; ///Compute direction unit vector of the geometry. MGUnit_vector direction(const MGPosition& param) const; ///Return tangent vector at the given point. /// 与えられた点における曲線の接ベクトルを返す。 virtual MGUnit_vector direction(double) const; ///////display member function. virtual void display_arrows(mgSysGL& sgl)const; virtual void display_break_points(mgSysGL& sgl)const; virtual void display_curvatures( mgSysGL& sgl,///& crv_list, ///=order(), order() is assumed. )const; ///get the a divide number for offset, intersection, or others. virtual int divide_number() const{return offset_div_num(param_range());}; ///Draw this curve into vbo, approximating with polyline. virtual void drawSE( mgVBO& vbo,///& sts,///=0. double& torsion ///& param)const; ///Test if this curve has the same direction with curve2. ///Test at the point s(of this) and t(of curve2). ///Function's return value is true if they have the same direction. ///"same direction" means their tangent vectors have the angle less than 90 degree. bool has_same_direction_at( double s, const MGCurve& curve2, double t )const; /// Return This object's typeID virtual long identify_type() const=0; ///Test if input parameter value is inside parameter range of the line. virtual bool in_range(double t) const; ///Test if input parameter value is inside parameter range of the line. bool in_range(const MGPosition& t) const; ///Curve to curve intersection. /// Curve と Curve の交点を求める。 MGCCisect_list intersect_brute_force(const MGCurve&) const; ///Curve to curve intersection. ///***Caution***intersect can be used only for finite curve, i.e. ///parameter range of the computation is only from param_s() to param_e(). ///For example, intersect cannot be applied to infinite straight line. virtual MGCCisect_list intersect(const MGCurve&) 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; ///Provide divide number of curve span for function intersect. virtual int intersect_dnum()const=0; ///intersections with a plane. MGCSisect_list intersect_with_plane(const MGPlane& surf)const; ///Intersection of Curve and other geometry. virtual MGCCisect_list isect(const MGCurve& curve2)const=0; virtual MGCCisect_list isect(const MGStraight& curve2)const=0; virtual MGCCisect_list isect(const MGRLBRep& curve2)const; virtual MGCCisect_list isect(const MGEllipse& curve2)const; virtual MGCCisect_list isect(const MGLBRep& curve2)const; virtual MGCCisect_list isect(const MGSurfCurve& curve2)const=0; virtual MGCCisect_list isect(const MGBSumCurve& curve2)const; MGCCisect_list isect(const MGTrimmedCurve& curve2)const; MGCCisect_list isect(const MGCompositeCurve& curve2)const; virtual MGCSisect_list isect(const MGSurface& surf)const=0; virtual MGCSisect_list isect(const MGPlane& surf)const=0; virtual MGCSisect_list isect(const MGSphere& surf)const=0; virtual MGCSisect_list isect(const MGCylinder& surf)const=0; virtual MGCSisect_list isect(const MGSBRep& surf)const=0; virtual MGCSisect_list isect(const MGRSBRep& surf)const=0; virtual MGCSisect_list isect(const MGBSumSurf& surf)const=0; MGCSisect_list isect(const MGFSurface& fs)const{return fs.isect(*this);}; virtual MGCSisect_list isect(const MGFace&)const; ///Intersection of a shell and a curve. MGCFisect_vector isect(const MGShell& shl) const; ///Compute intersection point of 1D sub curve of original curve. ///Parameter values of intersection point will be returned. MGCParam_list isect_1D( double f, ///< Coordinate value int coordinate=0 ///< Coordinate kind of the data f(from 0). ) const; ///Test if this is a Bezier Curve. ///Functions's return value is true if Bezier, false if not. ///If input ordr>=2, order is also tested if this Bezier's order is the same as input order. ///If input ordr<=1, any ordr>=2 is allowed for Bezier curve. ///Bezier curve is defined as follows. Here t=knot_vector(), k is this LBRep's order, ///n=bdim(), and m=(n-k)/(k-1). ///(1) n=k+(k-1)*m. ///(2) t(0)=t(1)=,...,=t(k-1)=0 ///(3) t(i)=t(i+1)=,...,=t(i+k-2)=j+1 /// for i=k, k+(k-1),...,k+j*(k-1) and j=0,...,m-1. ///(4) t(n)=t(n+1)=,...,=t(n+k-1)=m+1 virtual const MGLBRep* is_Bezier(int ordr=0)const; ///Test if this is a closed curve. /// 曲線が閉曲線かどうかを返す bool is_closed()const{return start_point()==end_point();}; ///Terst if this is a closed curve, given the tolerance. bool is_closedWithError(double err)const; ///Test if this cure is co-planar with the 2nd curve curve2. ///MGPlane expression will be out to plane if this is co-planar. ///Function's return value is true if co-planar. virtual bool is_coplanar(const MGCurve& curve2, MGPlane& plane)const; ///Test if the input parameter t is the start point parameter or not. virtual bool is_startpoint_parameter(double t)const; ///Test if the input parameter t is the start point parameter or not. virtual bool is_endpoint_parameter(double t)const; ///Test if the vector from P to this->eval(t) is perpendicular. ///Perpendicular to the tangent of this curve at t. bool is_perpendicular(const MGPosition& P, double t)const; ///Test if this cure is linear or not, that is, is straight or not. ///MGStraight expression will be out to straight if this is linear or not. ///Function's return value is true if linear. virtual bool is_linear(MGStraight& straight)const; ///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. virtual bool is_planar(MGPlane& plane)const; ///Access to i-th element of knot virtual double knot(int i) const=0; ///Returns the knot vector of the curve. virtual const MGKnotVector& knot_vector() const=0; ///Returns the knot vector of the curve. MGKnotVector& knot_vector(); ///Cmpute curve length of the interval. ///If t1 is greater than t2, return negative value. /// 与えられたパラメータ値間の曲線の長さを返す。 /// パラメータが昇順で与えられたときは正値、降順のときは負値を返す。 virtual double length(double t1, double t2) const; ///Compute whole curve length. ///If the curve is infinite, return -1. /// 自身の曲線が有界の場合、その曲線の距離を返却する。非有界の場 /// 合はー1を返却をする。 virtual double length() const {return length(param_s(), param_e());} ///Inverse function of length. ///Compute the point that is away from the point t by length len. /// lengthの逆関数。指定パラメータtで示される点から指定距離len /// 曲線上に沿って離れた点を示すパラメータ値を返す。 virtual double length_param( double t, double len) const; ///Update this by limiting the parameter range of the curve. /// 自身に指定したパラメータ範囲のlimitをつける. virtual MGCurve& limit(const MGInterval& rng) = 0; MGCurve& limit(double t0, double t1); ///Return manifold dimension, 0:point, 1:curve, 2:surface. int manifold_dimension() const{ return 1;}; ///Negate the curve direction(曲線の方向を反転する). virtual void negate() = 0; ///Obtain the parameter value to t when this curve is negated by "negate()". virtual double negate_param(double t)const= 0; ///Transform the coordinates of boundary of this geometry so that ///new coordinate of boundary is the same coordinate as the new one of ///this geometry after negate() of this geometry is done. ///That is, boundary coordinates are parameter world of this geometry. void negate_transform(MGGeometry& boundary)const; ///Offset of costant deviation from this curve. ///一定オフセット関数 ///オフセット方向は、法線方向から見て入力曲線の進行方向左側を正とする。 ///法線ベクトルがヌルの場合、始点において曲率中心方向を正とする。ただし、曲率中心へ曲率半径以上のオフセット ///は行わない。トレランスはline_zero()を使用している。戻り値は、オフセット曲線リストが返却される。 ///If the norm_vector is given, the positive offset direction decide ///to left hand side from ahead, or the direction to center of curvature at start parameter. ///the offset value is less than radius of curvature. line_zero() is used. virtual MGPvector offset( double ofs_value, ///<オフセット量 const MGVector& norm_vector = mgNULL_VEC ///<法線ベクトル ) const; ///Offset of variable deviation from this curve. ///可変オフセット関数 ///オフセット量は空間次元1の線B表現で与えられる。 ///オフセット方向は、法線方向から見て入力曲線の進行方向左側を正とする。 ///法線ベクトルがヌルの場合、始点において曲率中心方向を正とする。ただし、曲率中心へ曲率半径以上のオフセット ///は行わない。トレランスはline_zero()を使用している。戻り値は、オフセット曲線リストが返却される。 ///If the norm_vector is given, the positive offset direction decide ///to left hand side from ahead, or the direction to center of curvature at start parameter. ///the offset value is less than radius of curvature. line_zero() is used. virtual MGPvector offset( const MGLBRep& ofs_value_lb, ///<空間次元1の線B表現で示したオフセット量 const MGVector& norm_vector = mgNULL_VEC ///<法線ベクトル ) const; ///Costant offset curve of C2 continuous curve. ///C2連続曲線の一定オフセット関数 ///オフセット方向は、法線方向から見て入力曲線の進行方向左側を正とする。 ///法線ベクトルがヌルの場合、始点において曲率中心方向を正とする。ただし、曲率中心へ曲率半径以上のオフセット ///は行わない。トレランスはline_zero()を使用している。戻り値は、オフセット曲線が返却される。 ///costant offset curve of C2 continuous curve. if the norm_vector is given, the positive offset direction ///decide to left hand side from ahead, or the direction to center of curvature at start parameter. ///the offset value is less than radius of curvature. line_zero() is used. virtual MGLBRep offset_c2( double ofs_value, ///<オフセット量 const MGVector& norm_vector = mgNULL_VEC ///<法線ベクトル ) const; ///Valuable offset curve of C2 continuous curve. ///C2連続曲線の可変オフセット関数 ///オフセット量は空間次元1の線B表現で与えられる。 ///オフセット方向は、法線方向から見て入力曲線の進行方向左側を正とする。 ///法線ベクトルがヌルの場合、始点において曲率中心方向を正とする。ただし、曲率中心へ曲率半径以上のオフセット ///は行わない。トレランスはline_zero()を使用している。戻り値は、オフセット曲線が返却される。 ///valuable offset curve of C2 continuous curve. if the norm_vector is given, the positive offset direction ///decide to left hand side from ahead, or the direction to center of curvature at start parameter. ///the offset value is less than radius of curvature. line_zero() is used. virtual MGLBRep offset_c2( const MGLBRep& ofs_value_lb, ///<空間次元1の線B表現で示したオフセット量 const MGVector& norm_vector = mgNULL_VEC ///<法線ベクトル ) const; ///@cond ///get the number of division for offset. ///オフセットで使用する、あるパラメータ範囲の分割数を求める virtual int offset_div_num( const MGInterval& interval ///<分割数を求めるパラメータ範囲 )const; ///@endcond ///Test if given point is on the curve or not. ///If given point is on the curve, return parameter ///value of the curve. Even if not, return nearest point's parameter t. /// 指定点が自身上にあるかを調べる。曲線上にあれば,そのパラメーター値を, /// なくても最近傍点のパラメータ値を返す。 /// Function's return value is >0 if the point is on the curve, /// and 0 if the point is not on the curve. virtual bool on( const MGPosition& point,///0 if the point is on the geometry, /// and 0 if the point is not on the geometry. bool on( const MGPosition& P,///=t1) indicates no range specified. const MGPosition& P, ///=s1, no limit for this parameter range. const MGCurve& curve2, ///<2nd curve. double t0, ///=t1, no limit for curve2 parameter range. double sg, ///=0: number of curves obtained, <0 : Some error detected. virtual int project( const MGFSurface& surf, //given surface. MGPvector& vec_crv_uv, //uv projection curve will be appended. MGPvector& vec_crv, //3d projection curve will be appended. const MGVector& vec //projection vector. //if vec = NULL then calculate perpendicular project. )const; ///Round t into curve's parameter range. /// 入力パラメータをパラメータ範囲でまるめて返却する。 virtual double range(double t) const; ///Round t into geometry's parameter range. /// 入力パラメータをパラメータ範囲でまるめて返却する。 ///t's space dimension is geometry's manifold dimension. MGPosition range(const MGPosition& t) const; ///Rebuild this curve. std::unique_ptr rebuild( int how_rebuild=1, ///< intdicates how rebuild be done. ///< =0: no approximation(only parameter change) ///< =1: if this is rational spline(MGRLBRep), reconstructed with new knot configuration ///< as rational spline(MGRLBRep). ///< Otherwise approximated by non-rational spline(MGLBRep) with new knot configuration. ///< =2: approximated by non-rational spline(MGLBRep) with new knot configuration ///< if this is rational spline. If this is not rational spline, same as =1. int parameter_normalization=2, ///< Indicates how the parameter normalization be done: ///< =0: no parameter normalization. ///< =1: normalize to range=(0., 1.); ///< =2: normalize to make the average length of the 1st derivative ///< is as equal to 1. as possible. ///< =3: specify parameter range in param_range. double tol=-1., ///=4 is recommended. ///< When order=0 is input, the original order is unchanged if this curve is ///< MGLBRep or MGRLBRep. Otherwise order is set to 4. const double* param_range=0 /// scalePolar( double angleBase,///t1, whole range of this. const MGPosition& P, ///=2; ///If this space dimension is lager than 2, the remaining coordinates are set unchanged ///to MGLBRep. virtual std::unique_ptr PolarCoordinatesLBRep()const; /// Output virtual function. virtual std::ostream& out(std::ostream&) const; virtual std::string whoami()const{return "Curve";}; protected: ///メンバデータを読み出す関数. /// ここでは処理対象となるデータメンバが無いので何も処理をしない。 virtual void ReadMembers(MGIfstream& buf); ///メンバデータを書き込む関数. /// ここでは処理対象となるデータメンバが無いので何も処理をしない。 virtual void WriteMembers(MGOfstream& buf) const; ///Compute intersection point of 1D sub curve of original curve. ///Parameter values of intersection point will be returned. virtual MGCParam_list intersect_1D( double f, ///< Coordinate value int coordinate=0 ///< Coordinate kind of the data f(from 0). ) const; ///Approximate this curve as a MGLBRep curve from knot_vector[is] to [ie]. ///This is an internal program of MGLBRep constructor. void approximate_as_LBRep2( MGLBRep& lb, ///param_e(), extension will be done at the end point. double dk, /// oneD( const double g[4] ///& ofs_crvl ///<オフセットカーブリスト )const; ///法線ベクトルが指定されていないときの処理 int offset_proc( const MGLBRep& ofs_value_lb, ///<オフセット量 MGPvector& ofs_crvl ///<オフセットカーブリスト )const; ///法線ベクトルが指定されているC2連続曲線のオフセット int offset_norm_c2_proc( const MGLBRep& ofs_value_lb, ///<オフセット量 const MGVector& norm_vector, ///<法線ベクトル MGLBRep& ofs_brep ///<オフセットカーブ )const; ///法線ベクトルが指定されていないC2連続曲線のオフセット int offset_c2_proc( const MGLBRep& ofs_value_lb, ///<オフセット量 MGLBRep& ofs_brep, ///<オフセットカーブ MGUnit_vector& preN, ///<前回のノーマルベクトル int& freverse ///<向きを逆にしているというフラグ )const; ///曲線を折れで分割する(オフセット量を示す曲線の折れついても分割する) int divide_multi_ofs( const MGLBRep& ofs_value_lb, ///<オフセット量を示す曲線 MGPvector& brep_list ///<分割した曲線リスト )const; ///2本のB表現曲線を接続する(同じ種類のとき) ///join LBRep or RLBRep respectively. ///virtual MGCurve* join(const MGCurve& crv1) const; ///曲線をオフセットするのに十分分割したノットベクトルを返却する ///オフセット量曲線も考慮に入れ、分割数の多い方にあわせている。 MGKnotVector offset_make_knotvector(const MGLBRep& ofs_value_lb)const; friend class MGFace; friend class MGFSurface; friend class MGSurface; friend class MGLBRep; friend class MGTrimmedCurve; friend class MGSurfCurve; friend class MGCompositeCurve; friend class MGBSumCurve; }; ///@cond ///The class for function object for mgGausp to compute the length() of the curve. class MGCurveLengthDrive{ const MGCurve* m_curve; public: MGCurveLengthDrive(const MGCurve* curve):m_curve(curve){;}; ///Compute the length of the 1st derivative at the curve parameter t. double operator()(double t) const; }; ///The class for function object for mgDefint to compute the length_param() of the curve. class MGCurveLenParamDrive { const MGCurve* m_curve; double m_len, m_ts; public: MGCurveLenParamDrive(const MGCurve* curve, double len, double ts) :m_curve(curve), m_len(len), m_ts(ts){;}; double operator()(double t)const; }; ///@endcond namespace MGCL{ ///Compute curvature in 3D space, ie, the value is not negative. extern double Curvature( const MGVector& v1, ///