メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ | 関連ページ

PHGeometry2D.h

00001 #ifndef PH_GEOMETRY2D_H
00002 #define PH_GEOMETRY2D_H
00003 
00004 ///////////////////////////////////////////////////////////////////////
00005 //Geometric Constraint System 2D
00006 /* 幾何拘束ソルバー
00007     - 使い方 ----------------------------------------------
00008     //ソルバを生成
00009     PHGeometry3D geo;
00010 
00011     //拘束を追加
00012     geo.Add(new ***(frame1, frame2)); //***は拘束の種類
00013     ...
00014 
00015     //拘束を解く
00016     //  結果によりframeの位置姿勢が更新される
00017     geo.Solve();
00018     -------------------------------------------------------
00019     //拘束の種類
00020     
00021 
00022     //メモ
00023     拘束は二つのframe間の等式拘束→frameをノード、拘束をエッジとするグラフ
00024     エッジは自由度を持つ(例えばボールジョイント拘束なら3,ヒンジ関節拘束なら1)
00025     全エッジの自由度を決定変数とし,全エッジの拘束を満足する値を求める
00026         →*frameの位置姿勢を決定変数にすると次元が大きくなるのでNG
00027 
00028     不等式拘束の問題:
00029     特にframeの形状が交差しない拘束は実現したい
00030         →ペナルティ法
00031         
00032 
00033     *関節軸の指定をメタセコで色つきの線分で指定するのは便利そう!
00034  */
00035 
00036 
00037 //開発責任者:田崎勇一 tazaki@cyb.mei.titech.ac.jp
00038 
00039 #include <Base/Affine.h>
00040 #include <FileIO/FIDocScene.h>
00041 #include <SceneGraph/SGScene.h>
00042 #include <vector>
00043 
00044 using namespace PTM;
00045 namespace Spr{;
00046 
00047 //Geometry2D内部namespace
00048 namespace PHG2{
00049     //拘束の種類
00050     /*enum PHConstraint2DType{
00051         PHG2_POINT_TO_POINT,    //点−点拘束:2点を一致させる
00052         PHG2_POINT_TO_LINE,     //点−線拘束:点を線上に拘束する
00053         PHG2_POINT_TO_ARC,
00054         PHG2_LINE_TO_LINE,
00055         PHG2_LINE_TO_ARC,
00056         PHG2_ARC_TO_ARC,
00057         PHG2_PARALLEL,          //平行拘束:2線をなるべく小さな回転で平行にする
00058         PHG2_ANGLE,             //角度拘束:lhsのベクトルp0->p1を基準とするrhsのベクトルq0->q1の角度を
00059                                 //  任意の値(符号付き)に拘束する
00060         PHG2_FIX,               //固定拘束:
00061     };*/
00062 
00063     //充分小さな値
00064     static const double Epsilon = 1.0e-5;
00065 
00066     //自由度
00067     //  現在の実装ではT1R1となるケースは存在しない
00068     enum DOF{
00069         T0R0,
00070         T0R1,
00071         T1R0,
00072         T2R0,
00073         T2R1
00074     };
00075 
00076     //PHConstraint2D::Solveの戻り値
00077     enum Result{
00078         AGAIN,      //もう一度評価希望
00079         SOLVED,     //解けた
00080         NEW,        //新しい拘束が1つ生じた
00081         ILLPOSED,   //解決不能
00082         OVER,       //過剰拘束
00083         REDUNDANT,  //冗長拘束
00084         ERROR       //その他のエラー
00085     };
00086 
00087     typedef float Float;
00088     typedef Vec2f Vector2;
00089     /*class Vector2 : public SGObject, public Vec2f{
00090     public:
00091         SGOBJECTDEF(Vector2);
00092         Vector2& operator=(const Vec2f& v){
00093             *(Vec2f*)this = v;
00094             return *this;
00095         }
00096     };*/
00097     
00098     DEF_RECORD(XVector2, {
00099         GUID Guid(){return WBGuid("ec045bba-b265-4511-973d-500656055f40");}
00100         Float x;
00101         Float y;
00102     });
00103 
00104     //#define array
00105 
00106     //子ノード:
00107     //Frame x 1.このFrameのxy平面が動作面となる.未指定ならグローバルフレーム
00108     //拘束 x N > 0.
00109     DEF_RECORD(XGeometry2DEngine, {
00110         GUID Guid(){ return WBGuid("a59cd5af-d032-421f-a3ce-24920fd84222"); }
00111     });
00112 
00113     DEF_RECORD(XPointToPoint2D, {
00114         GUID Guid(){ return WBGuid("e4fa6c65-eddb-473c-96e9-9300d63875b0"); }
00115         Vector2 point_l;
00116         Vector2 point_r;
00117     });
00118 
00119     DEF_RECORD(XPointToLine2D, {
00120         GUID Guid(){ return WBGuid("1b0bbd07-7d79-4f95-ae7a-660e8fe05ed5"); }
00121         Vector2 point;
00122         Vector2 line0;
00123         Vector2 line1;
00124     });
00125 
00126     DEF_RECORD(XPointToArc2D, {
00127         GUID Guid(){ return WBGuid("6669a0c5-6ad0-4f58-84e5-98673b2cd03d"); }
00128         Vector2 point;
00129         Vector2 center;
00130         Float   radius;
00131         Float   limit0;
00132         Float   limit1;
00133     });
00134 
00135     DEF_RECORD(XLineToLine2D, {
00136         GUID Guid(){ return WBGuid("2e675bc7-c8a2-42bd-9d18-02e60e8f8b6a"); }
00137         Vector2 line0_l;
00138         Vector2 line1_l;
00139         Vector2 line0_r;
00140         Vector2 line1_r;
00141     });
00142 
00143     DEF_RECORD(XLineToArc2D, {
00144         GUID Guid(){ return WBGuid("f9e509e9-3010-41dd-9cf1-c9c6f6fb76ae"); }
00145         Vector2 line0;
00146         Vector2 line1;
00147         Vector2 center;
00148         Float   radius;
00149         Float   limit0;
00150         Float   limit1;
00151     });
00152 
00153     DEF_RECORD(XArcToArc2D, {
00154         GUID Guid(){ return WBGuid("41bc8040-7536-4bf2-b66d-da3f5a8f2ffc"); }
00155         Vector2 center_l;
00156         Float   radius_l;
00157         Float   limit0_l;
00158         Float   limit1_l;
00159         Vector2 center_r;
00160         Float   radius_r;
00161         Float   limit0_r;
00162         Float   limit1_r;
00163     });
00164 
00165     DEF_RECORD(XParallel2D, {
00166         GUID Guid(){ return WBGuid("cfd3c326-485a-42b7-8311-63bbbf21c58c"); }
00167         Float   dir_l;
00168         Float   dir_r;
00169     });
00170 
00171     DEF_RECORD(XAngle2D, {
00172         GUID Guid(){ return WBGuid("66cc9fe9-b9b6-46a8-9c04-6049a6c2b782"); }
00173         Float   offset_l;
00174         Float   offset_r;
00175         Float   angle;
00176     });
00177 
00178     DEF_RECORD(XFix2D, {
00179         GUID Guid(){ return WBGuid("8a3c63cf-639e-408f-8075-44c35f78c539"); }
00180         Vector2 offset;
00181         Float   angle;
00182     });
00183 
00184     //外部コンポーネントとリンクする内部クラス
00185     class Frame : public UTRefCount{
00186     public:
00187         UTRef<SGFrame>  frame;
00188         DOF dof;            //平行移動、回転の各自由度
00189         Vec2d       center;         //T0R1時の回転中心
00190         Vec2d       range0, range1; //T1R0時の平行移動範囲
00191 
00192         Vec2d       position;       //位置
00193         double      angle;          //角度
00194 
00195         //ローカル座標⇔ワールド座標
00196         Vec2d toWorld(const Vec2d& pl){
00197             return Matrix2d::Rot(angle) * pl + position;
00198         }
00199         Vec2d toLocal(const Vec2d& pw){
00200             return Matrix2d::Rot(-angle) * (pw - position);
00201         }
00202 
00203         /*PHG2Frame& operator=(const PHG2Frame& src){
00204             dof = src.dof;
00205             center = src.center;
00206             range0 = src.range0;
00207             range1 = src.range1;
00208             position = src.position;
00209             angle = src.angle;
00210             return *this;
00211         }*/
00212         //operator SGFrame*(){return frame;}
00213         //operator const SGFrame*()const{return frame;}
00214 
00215         Frame(SGFrame* f):frame(f){
00216             dof = T2R1;
00217             angle = 0.0;
00218         }
00219         //Frame(const Frame& src){*this = src;}
00220     };
00221 
00222     //オブジェクトの配列
00223     class FrameList : public std::vector<UTRef<Frame> >{
00224     public:
00225         iterator find(SGFrame* fr){
00226             for(iterator it = begin(); it != end(); it++)
00227                 if((*it)->frame == fr)
00228                     return it;
00229             return end();
00230         }
00231         /*PHG2FrameList& operator=(const PHG2FrameList& src){
00232             for(const_iterator it = src.begin(); it != src.end(); it++)
00233                 push_back(new PHG2Frame(**it));
00234             return *this;
00235         }
00236         PHG2FrameList(){}
00237         PHG2FrameList(const PHG2FrameList& src){*this = src;}*/
00238     };
00239 
00240 }
00241 
00242 
00243 //拘束クラス
00244 class PHConstraintList2D;
00245 class PHConstraint2D : public SGObject{
00246 public:     
00247     //SGObjectの機能
00248     SGOBJECTDEFABST(PHConstraint2D);
00249     virtual bool AddChildObject(SGObject* o, SGScene* s);
00250     virtual bool DelChildObject(SGObject* o, SGScene* s);
00251 
00252 protected:
00253     //PHConstraint2DType    type;   //拘束の種類
00254     UTRef<PHG2Frame> lhs, rhs;  //拘束対象
00255 
00256     //複製を作成
00257     virtual PHConstraint2D* dup() = 0;//{return 0;}
00258     //拘束を解く
00259     virtual PHG2Result Solve(PHConstraintList2D& newcon) = 0;//{return PHG2_ERROR;}
00260 
00261     PHConstraint2D(){}
00262     PHConstraint2D(PHConstraint2DType _type/*, SGFrame* _lhs, SGFrame* _rhs*/){
00263         type = _type;
00264         //lhs = new PHG2Frame(_lhs);
00265         //rhs = new PHG2Frame(_rhs);
00266     }
00267     virtual ~PHConstraint2D(){}
00268 };
00269 
00270 //拘束のリスト
00271 class PHConstraintList2D : public std::list<UTRef<PHConstraint2D> >{
00272 public:
00273     PHConstraintList2D& operator=(const PHConstraintList2D& src){
00274         resize(src.size());
00275         iterator it0;
00276         const_iterator it1;
00277         for(it0 = begin(), it1 = src.begin();
00278             it0 != end();
00279             it0++, it1++){
00280             *it0 = (*it1)->dup();
00281         }
00282         return *this;
00283     }
00284     PHConstraintList2D(){}
00285     PHConstraintList2D(const PHConstraintList2D& src){*this = src;}
00286 };
00287         
00288 //本体
00289 class PHGeometry2DEngine : public SGBehaviorEngine{
00290 public:     
00291     SGOBJECTDEF(PHGeometry2DEngine);
00292 
00293     ///エンジンとしての機能
00294     virtual bool AddChildObject(SGObject* o, SGScene* s);
00295     virtual bool DelChildObject(SGObject* o, SGScene* s);
00296     virtual int GetPriority() const {return SGBP_GEOMETRYENGINE;}
00297     virtual void Step(SGScene* s);
00298     virtual void Loaded(SGScene* scene);
00299     virtual void Clear(SGScene* s);
00300     virtual size_t NChildObjects(){ return frames.size(); }
00301     virtual SGObject* ChildObject(size_t i){ return (SGObject*)&*(frames[i]); }
00302 
00303     ///手動操作用関数
00304     ///拘束を追加する
00305     PHConstraint2D*     Add(PHConstraint2D* con, SGFrame* lhs, SGFrame* rhs);
00306 
00307     ///拘束を削除する
00308     void                Remove(PHConstraint2D*);
00309 
00310     ///拘束リストの取得
00311     //const PHConstraintList2D& Constraints()const{return cons;}
00312 
00313     ///拘束を解決する
00314     //void Solve();
00315 
00316     PHGeometry2DEngine(){}
00317     ~PHGeometry2DEngine(){}
00318 protected:
00319     UTRef<PHG2Frame>    plane;
00320     PHG2FrameList       frames;
00321     PHConstraintList2D  cons, cons_tmp;
00322     
00323     void        _Preprocess();
00324     void        _Postprocess();
00325 };
00326 
00327 ////////////////////////////////////////////////////////////////////////////////////////////////
00328 //  色々な拘束
00329     
00330 //点−点拘束
00331 class PHPointToPoint2D : public PHConstraint2D, public PHG2::XPointToPoint2D{
00332 public:
00333     SGOBJECTDEF(PHPointToPoint2D);
00334     PHPointToPoint2D(){}
00335     PHPointToPoint2D(
00336         /*SGFrame* _lhs, */const Vec2f& _p,
00337         /*SGFrame* _rhs, */const Vec2f& _q):
00338         PHConstraint2D(PHG2_POINT_TO_POINT/*, _lhs, _rhs*/)
00339         {point_l = _p; point_r = _q;}
00340     PHConstraint2D* dup(){return new PHPointToPoint2D(lhs->frame, point_l, rhs->frame, point_r);}
00341     PHG2Result Solve(PHConstraintList2D&);
00342 };
00343 
00344 //点−線拘束
00345 class PHPointToLine2D : public PHConstraint2D, public PHG2::XPointToLine2D{
00346 public:
00347     SGOBJECTDEF(PHPointToLine2D);
00348     PHPointToLine2D(){}
00349     PHPointToLine2D(
00350         SGFrame* _lhs, const Vec2f& _p,
00351         SGFrame* _rhs, const Vec2f& _q0, const Vec2f& _q1):
00352         PHConstraint2D(PHG2_POINT_TO_LINE, _lhs, _rhs)
00353         {point = _p; line0 = _q0; line1 = _q1;}
00354     PHConstraint2D* dup(){return new PHPointToLine2D(lhs->frame, point, rhs->frame, line0, line1);}
00355     PHG2Result Solve(PHConstraintList2D&);
00356 };
00357 
00358 //点−円拘束
00359 class PHPointToArc2D : public PHConstraint2D, public PHG2::XPointToArc2D{
00360 public:
00361     SGOBJECTDEF(PHPointToArc2D);
00362     PHPointToArc2D(){}
00363     PHPointToArc2D(
00364         SGFrame* _lhs, const Vec2f& _p,
00365         SGFrame* _rhs, const Vec2f& _c, float _r, float _s0, float _s1):
00366         PHConstraint2D(PHG2_POINT_TO_ARC, _lhs, _rhs)
00367         {point = _p; center = _c; radius = _r; limit0 = _s0; limit1 = _s1;}
00368     PHConstraint2D* dup(){return new PHPointToArc2D(lhs->frame, point, rhs->frame, center, radius, limit0, limit1);}
00369     PHG2Result Solve(PHConstraintList2D&);
00370 };
00371 
00372 //線−線
00373 class PHLineToLine2D : public PHConstraint2D, public PHG2::XLineToLine2D{
00374 public:
00375     SGOBJECTDEF(PHLineToLine2D);
00376     PHLineToLine2D(){}
00377     PHLineToLine2D(
00378         SGFrame* _lhs, const Vec2f& _p0, const Vec2f& _p1,
00379         SGFrame* _rhs, const Vec2f& _q0, const Vec2f& _q1):
00380         PHConstraint2D(PHG2_LINE_TO_LINE, _lhs, _rhs)
00381         {line0_l = _p0; line1_l = _p1; line0_r = _q0; line1_r = _q1;}
00382     PHConstraint2D* dup(){return new PHLineToLine2D(lhs->frame, line0_l, line1_l, rhs->frame, line0_r, line1_r);}
00383     PHG2Result Solve(PHConstraintList2D&);
00384 };
00385 
00386 //線−円拘束
00387 class PHLineToArc2D : public PHConstraint2D, public PHG2::XLineToArc2D{
00388 public:
00389     SGOBJECTDEF(PHLineToArc2D);
00390     PHLineToArc2D(){}
00391     PHLineToArc2D(
00392         SGFrame* _lhs, const Vec2f& _p0, const Vec2f& _p1,
00393         SGFrame* _rhs, const Vec2f& _c, float _r, float _s0, float _s1):
00394         PHConstraint2D(PHG2_LINE_TO_ARC, _lhs, _rhs)
00395         {line0 = _p0; line1 = _p1; center = _c; radius = _r; limit0 = _s0; limit1 = _s1;}
00396     PHConstraint2D* dup(){return new PHLineToArc2D(lhs->frame, line0, line1, rhs->frame, center, radius, limit0, limit1);}
00397     PHG2Result Solve(PHConstraintList2D&);
00398 };
00399 
00400 //円−円拘束
00401 class PHArcToArc2D : public PHConstraint2D, public PHG2::XArcToArc2D{
00402 public:
00403     SGOBJECTDEF(PHArcToArc2D);
00404     PHArcToArc2D(){}
00405     PHArcToArc2D(
00406         SGFrame* _lhs, const Vec2f& _c0, float _r0, float _s00, float _s01,
00407         SGFrame* _rhs, const Vec2f& _c1, float _r1, float _s10, float _s11):
00408         PHConstraint2D(PHG2_ARC_TO_ARC, _lhs, _rhs){
00409         center_l = _c0; radius_l = _r0; limit0_l = _s00; limit1_l = _s01;
00410         center_r = _c1; radius_r = _r1; limit0_r = _s10; limit1_r = _s11;
00411     }
00412     PHConstraint2D* dup(){return new PHArcToArc2D(lhs->frame, center_l, radius_l, limit0_l, limit1_l, rhs->frame, center_r, radius_r, limit0_r, limit1_r);}
00413     PHG2Result Solve(PHConstraintList2D&);
00414 };
00415 
00416 //平行拘束
00417 class PHParallel2D : public PHConstraint2D, public PHG2::XParallel2D{
00418 public:
00419     SGOBJECTDEF(PHParallel2D);
00420     PHParallel2D(){}
00421     PHParallel2D(
00422         SGFrame* _lhs, float _theta0,
00423         SGFrame* _rhs, float _theta1):
00424         PHConstraint2D(PHG2_PARALLEL, _lhs, _rhs)
00425         {dir_l = _theta0; dir_r = _theta1;}
00426     PHConstraint2D* dup(){return new PHParallel2D(lhs->frame, dir_l, rhs->frame, dir_r);}
00427     PHG2Result Solve(PHConstraintList2D&);
00428 };
00429 
00430 //角度拘束
00431 class PHAngle2D : public PHConstraint2D, public PHG2::XAngle2D{
00432 public:
00433     SGOBJECTDEF(PHAngle2D);
00434     PHAngle2D(){}
00435     PHAngle2D(
00436         SGFrame* _lhs, float _theta0,
00437         SGFrame* _rhs, float _theta1,
00438         float _phi):
00439         PHConstraint2D(PHG2_ANGLE, _lhs, _rhs)
00440         {offset_l = _theta0; offset_r = _theta1; angle = _phi;}
00441     PHConstraint2D* dup(){return new PHAngle2D(lhs->frame, offset_l, rhs->frame, offset_r, angle);}
00442     PHG2Result Solve(PHConstraintList2D&);
00443 };
00444 
00445 //固定拘束
00446 class PHFix2D : public PHConstraint2D, public PHG2::XFix2D{
00447 public:
00448     SGOBJECTDEF(PHFix2D);
00449     PHFix2D(){}
00450     PHFix2D(
00451         SGFrame* _lhs,
00452         SGFrame* _rhs, const Vec2d& _p, float _theta):
00453         PHConstraint2D(PHG2_FIX, _lhs, _rhs)
00454         {offset = _p; angle = _theta;}
00455     PHConstraint2D* dup(){return new PHFix2D(lhs->frame, rhs->frame, offset, angle);}
00456     PHG2Result Solve(PHConstraintList2D&);
00457 };
00458 
00459 ////////////////////////////////////////////////////////////////////////    
00460 //2次元幾何関数
00461 
00462 ///ある点まわりの回転
00463 inline void RotationAlong(Vec2d* position, double* angle, const Vec2d& center, double rot){
00464     *angle += rot;
00465     *position = Matrix2d::Rot(rot) * (*position - center) + center;
00466 }
00467 
00468 //ある点に最も近い直線上の点
00469 inline void NearestPoint(
00470     Vec2d* y,
00471     const Vec2d& p,
00472     const Vec2d& q, const Vec2d& u)
00473 {
00474     *y = q + PTM::dot(u, p - q) / u.square() * u;
00475 }
00476 
00477 //2直線の角度
00478 inline double Line_Line_Angle(
00479     const Vec2d& u0,
00480     const Vec2d& u1)
00481 {
00482     return atan2(PTM::cross(u0, u1), PTM::dot(u0, u1));
00483 }
00484 
00485 //2直線の交点
00486 inline bool Line_Line_Intersect(
00487     Vec2d* y,
00488     const Vec2d& p0, const Vec2d& u0,
00489     const Vec2d& p1, const Vec2d& u1)
00490 {
00491     //連立方程式
00492     Matrix2d A(u0, -u1);
00493     if(fabs(A.det()) < 0.0)return false;
00494     Vec2d s = A.inv() * (-p0 + p1);
00495     
00496     *y = p0 + s[0] * u0;
00497     return true;
00498 }
00499 
00500 //円と直線の交点
00501 //交差しない場合は互いに最も近い点を返す
00502 inline bool Line_Circle_Intersect(
00503     Vec2d* y0, Vec2d* y1,
00504     const Vec2d& p, const Vec2d& u,
00505     const Vec2d& c, double r)
00506 {
00507     //二次方程式の係数
00508     double A = u.square();
00509     double B = PTM::dot(u, (p - c));
00510     double C = (p - c).square() - r * r;
00511     //判別式
00512     double det = B * B - A * C;
00513     if(det < 0){
00514         //交差しないので最近点を求める
00515         NearestPoint(y0, c, p, u);          //直線上の最近点
00516         Vec2d c_y0 = *y0 - c;
00517         *y1 = c + r / c_y0.norm() * c_y0;   //円上の最近点
00518         return false;
00519     }
00520     //方程式の解と交点
00521     double det_root = sqrt(det);
00522     double s0 = (-B + det_root) / A, s1 = (-B - det_root) / A;
00523     *y0 = p + s0 * u, *y1 = p + s1 * u;
00524     return true;
00525 }
00526 
00527 //2円の交点
00528 //交差しない場合は互いに最も近い点を返す
00529 inline bool Circle_Circle_Intersect(
00530     Vec2d* y0, Vec2d* y1,
00531     const Vec2d& c0, double r0,
00532     const Vec2d& c1, double r1)
00533 {
00534     //中心間をつなぐベクトル
00535     Vec2d d = c1 - c0;
00536     double d_norm = d.norm();
00537     //円の半径
00538     //円同士の傾きと対応する回転行列
00539     double phi = atan2(d.Y(), d.X());
00540     Matrix2d rot = Matrix2d::Rot(phi);
00541     //判別式
00542     double det = 
00543         ( r0 + r1 + d_norm) * 
00544         ( r0 + r1 - d_norm) * 
00545         ( r0 - r1 + d_norm) * 
00546         (-r0 + r1 + d_norm);
00547     if(det < 0){
00548         //交差しないので最近点を求める
00549         *y0 = c0 + r0 / d_norm * d;
00550         *y1 = c1 - r1 / d_norm * d;
00551         return false;
00552     }
00553     //c0を原点、dをx軸とするフレームでの交点座標
00554     double h = sqrt(det) / (2 * d_norm);
00555     double w = sqrt(r0 * r0 - h * h);
00556     //交点
00557     *y0 = rot * Vec2d(w,  h) + c0;
00558     *y1 = rot * Vec2d(w, -h) + c0;
00559     return true;
00560 }
00561 
00562 //2円の共通接線
00563 //円c0上の接点をp0, p1, p2, p3に、c1上の接点をq0, q1, q2, q3に
00564 //接線の本数を返す(0, 2, 4のいずれかを返す。1, 3本は2円が接している状態で
00565 //起こるが
00566 inline int Circle_Circle_Tangent(
00567     const Vec2d& c0, double r0,
00568     const Vec2d& c1, double r1,
00569     Vec2d* p0, Vec2d* p1, Vec2d* p2, Vec2d* p3,
00570     Vec2d* q0, Vec2d* q1, Vec2d* q2, Vec2d* q3)
00571 {
00572     Vec2d d = c1 - c0;
00573     double d_norm = d.norm();
00574     double phi = atan2(d.Y(), d.X());
00575     //2円が中心を共有する場合
00576     if(d_norm < PHG2Epsilon)return 0;
00577     //判別式
00578     double det1 = (r0 - r1) / d_norm;
00579     double det2 = (r0 + r1) / d_norm;
00580     int nline;
00581     double theta;
00582     double _cos, _sin;
00583     //c0を原点として、dをx軸とする座標で計算を進める:
00584     //片方の円がもう一方を内包する場合
00585     if(fabs(det1) > 1.0 + PHG2Epsilon)
00586         return 0;
00587     //内接する場合
00588     if(fabs(det1) > 1.0 - PHG2Epsilon){
00589         //どっちが外側か
00590         *p0 = *q0 = Vec2d(r0 > r1 ? r0 : -r0, 0);
00591         nline = 1;
00592     }
00593     //2点で交差する場合
00594     else if(det2 > 1.0 + PHG2Epsilon){
00595         theta = acos(det1);
00596         _cos = cos(theta), _sin = sin(theta);
00597         *p0 = Vec2d(r0 * _cos,  r0 * _sin);
00598         *p1 = Vec2d(r0 * _cos, -r0 * _sin);
00599         *q0 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00600         *q1 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00601         nline = 2;
00602     }
00603     //外接する場合
00604     else if(det2 < PHG2Epsilon){
00605         *p0 = *q0 = Vec2d(r0, 0);
00606         theta = acos(det1);
00607         _cos = cos(theta), _sin = sin(theta);
00608         *p1 = Vec2d(r0 * _cos,  r0 * _sin);
00609         *p2 = Vec2d(r0 * _cos, -r0 * _sin);
00610         *q1 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00611         *q2 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00612         nline = 3;
00613     }
00614     //離れている場合
00615     else{
00616         theta = acos(det1);
00617         _cos = cos(theta), _sin = sin(theta);
00618         *p0 = Vec2d(r0 * _cos,  r0 * _sin);
00619         *p1 = Vec2d(r0 * _cos, -r0 * _sin);
00620         *q0 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00621         *q1 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00622         theta = acos(det2);
00623         _cos = cos(theta), _sin = sin(theta);
00624         *p2 = Vec2d(r0 * _cos,  r0 * _sin);
00625         *p3 = Vec2d(r0 * _cos, -r0 * _sin);
00626         *q2 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00627         *q3 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00628         nline = 4;
00629     }
00630     //最後に座標変換
00631     Matrix2d rot = Matrix2d::Rot(phi);
00632     *p0 = c0 + rot * *p0;
00633     *q0 = c0 + rot * *q0;
00634     *p1 = c0 + rot * *p1;
00635     *q1 = c0 + rot * *q1;
00636     *p2 = c0 + rot * *p2;
00637     *q2 = c0 + rot * *q2;
00638     *p3 = c0 + rot * *p3;
00639     *q3 = c0 + rot * *q3;
00640     return nline;
00641 }
00642 
00643 //pがq0, q1の間にあるかを判定
00644 inline bool Point_On_LineSegment(
00645     const Vec2d& p,
00646     const Vec2d& q0, const Vec2d& q1)
00647 {
00648     Vec2d u = p - q0, v = p - q1;
00649     return 
00650         fabs(PTM::cross(u, v)) < u.norm() * v.norm() * PHG2Epsilon &&
00651         PTM::dot(u, v) < PHG2Epsilon;
00652 }
00653 
00654 //pがc, rで表される円上にあるものとして、pが角度範囲[s0, s1]内にあるかを判定
00655 //ただしs0, s1はx軸を基準に反時計回り方向
00656 inline bool Point_On_Arc(
00657     const Vec2d& p,
00658     const Vec2d& c, double r, double s0, double s1)
00659 {
00660     while(s0 < -M_PI)s0 += 2 * M_PI;
00661     while(s0 >  M_PI)s0 -= 2 * M_PI;
00662     while(s1 < -M_PI)s1 += 2 * M_PI;
00663     while(s1 >  M_PI)s1 -= 2 * M_PI;
00664     if(s1 < s0)s1 += 2 * M_PI;
00665     
00666     Vec2d u = p - c;
00667     double s = atan2(u.Y(), u.X());
00668     if(s < s0)s += M_PI;
00669     if(s < s1)return true;
00670     return false;
00671 }
00672 
00673 }
00674 
00675 #endif

Springheadに対してSun Apr 16 01:57:54 2006に生成されました。  doxygen 1.4.1