00001 #ifndef CDQUICKHULL2DIMP_H
00002 #define CDQUICKHULL2DIMP_H
00003
00004 #include "CDQuickHull2D.h"
00005 #include <Base/Affine.h>
00006 #include <Base/BaseDebug.h>
00007 #include <vector>
00008 #include <float.h>
00009
00010 namespace Spr{;
00011
00012 template <class TVtx>
00013 void CDQHLine<TVtx>::Clear(){
00014 deleted = false;
00015 }
00016 template <class TVtx>
00017 bool CDQHLine<TVtx>::Visible(TVtx* p){
00018 Vec2d pos = p->GetPos();
00019 return pos*normal > dist;
00020 }
00021 template <class TVtx>
00022 int CDQHLine<TVtx>::GetVtxID(TVtx* v){
00023 int i;
00024 for(i=0; i<2; ++i) if(v == vtx[i]) break;
00025 return i;
00026 }
00027 template <class TVtx>
00028 void CDQHLine<TVtx>::CalcNormal(){
00029 Vec2d pos0 = vtx[0]->GetPos();
00030 Vec2d pos1 = vtx[1]->GetPos();
00031 Vec2d a = pos1 - pos0;
00032 normal = Vec2d(-a.y, a.x);
00033 assert(normal.norm());
00034 normal.unitize();
00035 dist = pos0 * normal;
00036 }
00037 template <class TVtx>
00038 double CDQHLine<TVtx>::CalcDist(TVtx* v){
00039 Vec2d vPos = v->GetPos();
00040 Vec2d diffMin = vPos - Vec2d(vtx[0]->GetPos());
00041 return diffMin * normal;
00042 }
00043 template <class TVtx>
00044 void CDQHLine<TVtx>::Print(std::ostream& os) const {
00045 os << "Plane:";
00046 for(int i=0; i<2; ++i){
00047 os << " " << *vtx[i];
00048 }
00049 os << " d:" << dist << " n:" << normal;
00050 if (deleted) os << " del";
00051 os << std::endl;
00052 }
00053
00054 template <class TVtx>
00055 std::ostream& operator << (std::ostream& os, const CDQHLine<TVtx>& pl){
00056 pl.Print(os);
00057 return os;
00058 }
00059
00060 template <class TVtx>
00061 unsigned CDQHLines<TVtx>::size(){
00062 return end - begin;
00063 }
00064 template <class TVtx>
00065 CDQHLines<TVtx>::CDQHLines(int l):len(l), epsilon(1e-6), infinite(1e8){
00066 buffer = new CDQHLine[len];
00067 Clear();
00068 }
00069 template <class TVtx>
00070 void CDQHLines<TVtx>::Clear(){
00071 begin = buffer;
00072 end = begin;
00073 nLines = 0;
00074 }
00075 template <class TVtx>
00076 void CDQHLine<TVtx>::Reverse(){
00077 normal = -normal;
00078 dist = -dist;
00079 std::swap(vtx[0], vtx[1]);
00080 }
00081 template <class TVtx>
00082 CDQHLines<TVtx>::~CDQHLines(){
00083 delete [] buffer;
00084 }
00085
00086
00087
00088
00089 template <class TVtx>
00090 void CDQHLines<TVtx>::CreateConvexHull(TVtx** b, TVtx** e){
00091 if (e-b < 2){
00092 if (e-b == 1){
00093 end->Clear();
00094 end->vtx[0] = b[0];
00095 end->vtx[1] = b[0];
00096 end->neighbor[0] = end->neighbor[1] = end;
00097 end++;
00098 }
00099 return;
00100 }
00101 vtxBeginInput = b;
00102 vtxEndInput = e;
00103 vtxBegin = b;
00104 vtxEnd = e;
00105
00106 CreateFirstConvex();
00107 HULL_DEBUG_EVAL(
00108 DSTR << "First:" << begin->vtx[0]->GetPos() << begin->vtx[1]->GetPos() << std::endl;
00109 if ((begin->vtx[1]->GetPos() - begin->vtx[0]->GetPos()).norm() < 0.001) {
00110 DSTR << "same error" << std::endl;
00111 }
00112 DSTR << begin->dist << begin->normal << std::endl;
00113 )
00114 for(CDQHLine* cur = begin; cur != end; ++cur){
00115 if (cur->deleted) continue;
00116 TreatPlane(cur);
00117 assert(end < buffer+len);
00118 }
00119 }
00120
00121 template <class TVtx>
00122 void CDQHLines<TVtx>::Print(std::ostream& os) const {
00123 int num=0;
00124 for(const CDQHLine* it = begin; it != end; ++it){
00125 if (!it->deleted) num ++;
00126 }
00127 os << num << " lines." << std::endl;
00128 for(const CDQHLine* it = begin; it != end; ++it){
00129 it->Print(os);
00130 }
00131 }
00132
00133 template <class TVtx>
00134 void CDQHLines<TVtx>::CreateFirstConvex(){
00135 CDQHLines& lines = *this;
00136 double xMin, xMax;
00137 TVtxs::iterator it, xMinVtx, xMaxVtx;
00138 xMin = xMax = (*vtxBegin)->GetPos().X();
00139 xMinVtx = xMaxVtx = vtxBegin;
00140
00141 for(it = vtxBegin+1; it != vtxEnd; ++it){
00142 double x = (*it)->GetPos().X();
00143 if (x < xMin){
00144 xMin = x;
00145 xMinVtx = it;
00146 }
00147 if (x > xMax){
00148 xMax = x;
00149 xMaxVtx = it;
00150 }
00151 }
00152
00153 std::swap(*xMaxVtx, vtxBegin[0]);
00154 if (xMinVtx == vtxBegin){
00155 std::swap(*xMaxVtx, vtxBegin[1]);
00156 }else{
00157 std::swap(*xMinVtx, vtxBegin[1]);
00158 }
00159
00160
00161 lines.end->Clear();
00162 lines.end->vtx[0] = vtxBegin[1];
00163 lines.end->vtx[1] = vtxBegin[0];
00164 lines.end->CalcNormal();
00165 lines.end++;
00166
00167
00168 *lines.end = *lines.begin;
00169 lines.end->Reverse();
00170 lines.begin->neighbor[0] = lines.end;
00171 lines.begin->neighbor[1] = lines.end;
00172 lines.end->neighbor[0] = lines.begin;
00173 lines.end->neighbor[1] = lines.begin;
00174 lines.end++;
00175
00176 vtxBegin += 2;
00177 nLines = 2;
00178 }
00179
00180
00181
00182
00183 template <class TVtx>
00184 void CDQHLines<TVtx>::CreateCone(CDQHLine* cur, TVtx* top){
00185 cur->deleted = true;
00186 nLines --;
00187
00188 CDQHLine* horizon[2];
00189 for(int i=0; i<2; ++i){
00190 horizon[i] = cur->neighbor[i];
00191 while(horizon[i]->Visible(top) && nLines>1){
00192 horizon[i]->deleted = true;
00193 nLines --;
00194 horizon[i] = horizon[i]->neighbor[i];
00195 }
00196 }
00197
00198
00199 end->Clear();
00200 horizon[0]->neighbor[1] = end;
00201 end->vtx[0] = horizon[0]->vtx[1];
00202 end->vtx[1] = top;
00203 end->neighbor[0] = horizon[0];
00204 end->neighbor[1] = end+1;
00205 end->CalcNormal();
00206 end++;
00207 nLines ++;
00208
00209 end->Clear();
00210 horizon[1]->neighbor[0] = end;
00211 end->vtx[0] = top;
00212 end->vtx[1] = horizon[1]->vtx[0];
00213 end->neighbor[0] = end-1;
00214 end->neighbor[1] = horizon[1];
00215 end->CalcNormal();
00216 end++;
00217 nLines ++;
00218 }
00219
00220 template <class TVtx>
00221 bool CDQHLines<TVtx>::FindFarthest(CDQHLine* line){
00222 TVtx** maxVtx=NULL;
00223 double maxDist = epsilon;
00224 for(TVtx** it=vtxBegin; it!= vtxEnd; ++it){
00225 double dist = line->CalcDist(*it);
00226 if (dist > maxDist){
00227 maxDist = dist;
00228 maxVtx = it;
00229 }
00230 }
00231 if (maxVtx){
00232 std::swap(*vtxBegin, *maxVtx);
00233 vtxBegin++;
00234 #ifdef _DEBUG
00235 if ( vtxBegin[-1]->GetPos() == line->vtx[0]->GetPos()
00236 || vtxBegin[-1]->GetPos() == line->vtx[1]->GetPos()){
00237 DSTR << "Error: same position." << std::endl;
00238 for(int i=0; i<2; ++i){
00239 DSTR << "V" << i << ": " << line->vtx[i]->GetPos() << std::endl;
00240 }
00241 DSTR << "P : " << vtxBegin[-1]->GetPos() << std::endl;
00242 assert(0);
00243 }
00244 #endif
00245 return true;
00246 }
00247 return false;
00248 }
00249
00250
00251 template <class TVtx>
00252 TVtx** CDQHLines<TVtx>::DivideByPlaneR(CDQHLine* plane, TVtx** start, TVtx** end){
00253 double INNER_DISTANCE = epsilon * plane->dist;
00254 while(start != end){
00255 double d = -plane->CalcDist(*start);
00256 if (d <= INNER_DISTANCE){
00257 -- end;
00258 std::swap(*end, *start);
00259 }else{
00260 ++ start;
00261 }
00262 }
00263 return start;
00264 }
00265 template <class TVtx>
00266 TVtx** CDQHLines<TVtx>::DivideByPlane(CDQHLine* plane, TVtx** start, TVtx** end){
00267 double INNER_DISTANCE = epsilon * plane->dist;
00268 while(start != end){
00269 double d = plane->CalcDist(*start);
00270 if (d <= INNER_DISTANCE){
00271 -- end;
00272 std::swap(*end, *start);
00273 }else{
00274 ++ start;
00275 }
00276 }
00277 return start;
00278 }
00279
00280
00281 template <class TVtx>
00282 void CDQHLines<TVtx>::TreatPlane(CDQHLine* cur){
00283
00284 if (!FindFarthest(cur)) return;
00285 HULL_DEBUG_EVAL(
00286 DSTR << "Farthest:" << vtxBegin[-1]->GetPos();
00287 DSTR << " cmp:" << vtxBegin[-1]->GetPos()*cur->normal << " > " << cur->dist << std::endl;
00288 if (cur->dist < 0){
00289 DSTR << "faceDist:" << cur->dist << std::endl;
00290 }
00291 )
00292
00293 CreateCone(cur, vtxBegin[-1]);
00294 HULL_DEBUG_EVAL(
00295 if (!hor){
00296 DSTR << "No Horizon Error!!" << std::endl;
00297 assert(hor);
00298 }
00299 )
00300
00301 TVtx** inner = DivideByPlaneR(cur, vtxBegin, vtxEnd);
00302 for(CDQHLine* it=end-2; it!=end; ++it){
00303 HULL_DEBUG_EVAL(
00304 std::cout << "Inner:";
00305 for(TVtx** v = inner; v != vtxEnd; ++v){
00306 std::cout << **v;
00307 }
00308 std::cout << std::endl;
00309 );
00310 inner = DivideByPlane(it, inner, vtxEnd);
00311 }
00312 HULL_DEBUG_EVAL(
00313 std::cout << "InnerFinal:";
00314 for(TVtx** v = inner; v != vtxEnd; ++v){
00315 std::cout << **v;
00316 }
00317 std::cout << std::endl;
00318 );
00319 vtxEnd = inner;
00320 }
00321
00322 template <class TVtx>
00323 std::ostream& operator << (std::ostream& os, const CDQHLines<TVtx>& pls){
00324 pls.Print(os);
00325 return os;
00326 }
00327 template <class CDQHVtx2DSample>
00328 inline std::ostream& operator << (std::ostream& os, const TYPENAME CDQHLines<CDQHVtx2DSample>::TVtxs& f){
00329 f.Print(os); return os;
00330 }
00331
00332 inline void CDQHVtx2DSample::Print(std::ostream& os) const {
00333
00334 os << id_ << " ";
00335 }
00336 inline std::ostream& operator << (std::ostream& os, const CDQHVtx2DSample& f){
00337 f.Print(os); return os;
00338 }
00339
00340 }
00341
00342 #endif