00001 #ifndef CDQUICKHULL2D_H 00002 #define CDQUICKHULL2D_H 00003 00004 #include <Base/Affine.h> 00005 #include <Base/TQuaternion.h> 00006 #include <vector> 00007 00008 //#define HULL_DEBUG // デバッグ出力 00009 #ifdef HULL_DEBUG 00010 #define HULL_DEBUG_EVAL(x) x 00011 #else 00012 #define HULL_DEBUG_EVAL(x) 00013 #endif 00014 00015 namespace Spr{; 00016 00017 /// QuickHullで作られる面 00018 template <class TVtx> 00019 class CDQHLine{ 00020 public: 00021 Vec2d normal; ///< 面の法線 00022 double dist; ///< 面の原点からの距離 00023 00024 TVtx* vtx[2]; ///< 面を構成する頂点 00025 CDQHLine* neighbor[2]; ///< 隣の面 vtx[0] の隣が neighbor[0] 00026 bool deleted; ///< 削除された面はtrue 00027 void Clear(); ///< メモリクリア.使う前に呼ぶ. 00028 void Reverse(); ///< 辺の裏表をひっくり返す. 00029 bool Visible(TVtx* p); ///< 頂点 v から表側が見えるかどうか 00030 /// vの頂点番号を返す(0..1を返す).見つからなければ3を返す. 00031 int GetVtxID(TVtx* v); 00032 void CalcNormal(); ///< 法線ベクトルと距離を計算する. 00033 /// 点との距離を計算する.精度を考慮して一番近い点で計算する. 00034 double CalcDist(TVtx* v); 00035 /// デバッグ用表示 00036 void Print(std::ostream& os) const; 00037 }; 00038 00039 /// 面のバッファ 00040 template <class TVtx> 00041 class CDQHLines{ 00042 public: 00043 double epsilon; 00044 double infinite; 00045 00046 TVtx** vtxBeginInput; ///< 残っている頂点の先頭 00047 TVtx** vtxEndInput; ///< 残っている頂点の最後の次 00048 /// 頂点のVector 00049 class TVtxs: public std::vector<TVtx*>{ 00050 public: 00051 void Print(std::ostream& os) const{ 00052 for(TVtxs::const_iterator it = begin(); it != end(); ++it){ 00053 (*it)->Print(os); 00054 } 00055 } 00056 }; 00057 typedef CDQHLine<TVtx> CDQHLine; 00058 00059 CDQHLine* buffer; ///< バッファへのポインタ new する. 00060 int len; ///< バッファの長さ 00061 CDQHLine* begin; ///< 最初の辺 00062 CDQHLine* end; ///< 最後の辺の次 00063 TVtx** vtxBegin; ///< 残っている頂点の先頭 00064 TVtx** vtxEnd; ///< 残っている頂点の最後の次 00065 int nLines; ///< 辺の数 00066 unsigned size(); ///< 使用済みバッファのサイズ 00067 CDQHLines(int l); 00068 void Clear(); 00069 ~CDQHLines(); 00070 /** bからeまでの頂点から凸包を作る.使用した頂点はbからvtxBegin, 00071 使用しなかった頂点は,vtxBeginからeに移動する. 00072 beginからendは頂点を3つ含む面になる.それらの面うち凸包に使われた面 00073 は CDQHLine::deleted が false になっている. */ 00074 void CreateConvexHull(TVtx** b, TVtx** e); 00075 void Print(std::ostream& os) const; 00076 00077 private: 00078 /** 最初の凸多面体=2本の辺(表裏)を作る. 00079 できるだけ大きい辺を作ると効率が良い. */ 00080 void CreateFirstConvex(); 00081 /** 辺curと,その面から一番遠い頂点 top を受け取り, 00082 curとその周囲の辺を削除し,凸包にtopを含める. 00083 end[-1], end[-2]が新たに作られた辺になる. */ 00084 void CreateCone(CDQHLine* cur, TVtx* top); 00085 /** 一番遠くの頂点を見つける.見つけたらそれを頂点リストからはずす */ 00086 bool FindFarthest(CDQHLine* plane); 00087 /* 外側 内側 の順に並べる. 00088 外側の終わり=内側の始まりが inner */ 00089 TVtx** DivideByPlaneR(CDQHLine* plane, TVtx** start, TVtx** end); 00090 TVtx** DivideByPlane(CDQHLine* plane, TVtx** start, TVtx** end); 00091 /** 一つの面に対する処理を行う.一番遠くの頂点を見つけ, 00092 地平線を調べ,コーンを作り,内部の頂点をはずす.*/ 00093 void TreatPlane(CDQHLine* cur); 00094 }; 00095 00096 /// 頂点クラスの例 00097 class CDQHVtx2DSample{ 00098 public: 00099 ///@name QuickHullが使用するメンバ.必須. 00100 //@{ 00101 /// 頂点の位置 00102 Vec2f GetPos() const { return pos; } 00103 //@} 00104 public: 00105 Vec2f pos; ///< 位置 00106 int id_; 00107 void Print(std::ostream& os) const; 00108 }; 00109 00110 } 00111 00112 #endif