inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_CListContour 00005 #define inlib_CListContour 00006 00007 // G.Barrand : inline version of the one found in Lib of OSC 16.11. 00008 // This code is not mine and I keep it "as it is". 00009 00010 // Inheritance : 00011 #include "CContour" 00012 00013 #include <list> 00014 #include <ostream> 00015 #include <iomanip> //std::setprecision 00016 00017 namespace inlib { 00018 00019 // a list of point index referring to the secondary grid 00020 // Let i the index of a point, 00021 typedef std::list<unsigned int> CLineStrip; 00022 typedef std::list<CLineStrip*> CLineStripList; 00023 typedef std::vector<CLineStripList> CLineStripListVector; 00024 00025 class CListContour : public CContour 00026 { 00027 public: //CContour 00028 // Adding segment to line strips 00029 // See CContour::ExportLine for further details 00030 virtual void ExportLine(int iPlane,int x1, int y1, int x2, int y2); 00031 00032 public: 00033 CListContour(); 00034 virtual ~CListContour(){CleanMemory();} 00035 protected: //G.Barrand 00036 inline CListContour(const CListContour& a_from):CContour(a_from){} 00037 private: //G.Barrand 00038 inline CListContour& operator=(const CListContour&){return *this;} 00039 public: 00040 // retreiving list of line strip for the i-th contour 00041 CLineStripList* GetLines(unsigned int iPlane); 00042 00043 // Initializing memory 00044 virtual void InitMemory(); 00045 // Cleaning memory and line strips 00046 virtual void CleanMemory(); 00047 // Generate contour strips 00048 virtual void Generate(); 00049 00050 // Adding segment to line strips 00051 // See CContour::ExportLine for further details 00052 //void ExportLine(int iPlane,int x1, int y1, int x2, int y2); 00053 00054 // Basic algorithm to concatanate line strip. Not optimized at all ! 00055 bool CompactStrips(); 00057 void DumpPlane(unsigned int iPlane) const; 00058 00059 // Area given by this function can be positive or negative depending on the winding direction of the contour. 00060 double Area(CLineStrip* Line); 00061 00062 double EdgeWeight(CLineStrip* pLine, double R); 00063 bool PrintContour(std::ostream& a_out); 00064 protected: 00065 // Merges pStrip1 with pStrip2 if they have a common end point 00066 bool MergeStrips(CLineStrip* pStrip1, CLineStrip* pStrip2); 00067 // Merges the two strips with a welding threshold. 00068 bool ForceMerge(CLineStrip* pStrip1, CLineStrip* pStrip2,double); 00069 // returns true if contour is touching boundary 00070 bool OnBoundary(CLineStrip* pStrip); 00071 // L.Garnier : check specials case for CompactStrip 00072 bool SpecialCompactStripCase(double,double,double,double,double); 00073 00074 private: 00075 // array of line strips 00076 CLineStripListVector m_vStripLists; 00077 typedef unsigned int UINT; 00078 00079 private: 00080 inline static const char* _TT(const char* what) {return what;} 00081 00082 inline static void TRACE(const char* /*a_fmt*/,...) { 00083 //va_list args; 00084 //va_start(args,a_fmt); 00085 //::vprintf(s,a_fmt,args); 00086 //va_end(args); 00087 } 00088 inline static void PROBLEM(const char* what) {::printf("%s",what);} 00089 00090 inline static bool ASSERT_RET(bool what,const char* cmt) { 00091 if(!(what)) { 00092 ::printf("debug : ListContour : assert failure in %s\n",cmt); 00093 return false; 00094 } 00095 return true; 00096 } 00097 00098 inline static bool ASSERT_MERGE_RET(bool what,const char* cmt,CLineStrip* pStrip2) { 00099 if(!(what)) { 00100 ::printf("debug : ListContour : assert failure in %s\n",cmt); 00101 pStrip2->clear(); 00102 return false; 00103 } 00104 return true; 00105 } 00106 }; 00107 00108 00109 // implementation : 00110 inline CListContour::CListContour() 00111 : CContour() 00112 { 00113 } 00114 00115 inline void CListContour::Generate() 00116 { 00117 // generate line strips 00118 CContour::Generate(); 00119 // compact strips 00120 CompactStrips(); 00121 } 00122 00123 inline void CListContour::InitMemory() 00124 { 00125 CContour::InitMemory(); 00126 00127 CLineStripList::iterator pos; 00128 CLineStrip* pStrip; 00129 00130 if (!m_vStripLists.empty()) 00131 { 00132 UINT i; 00133 // reseting lists 00134 ASSERT(m_vStripLists.size() == GetNPlanes(),"CListContour::InitMemory::0"); 00135 for (i=0;i<GetNPlanes();i++) 00136 { 00137 for (pos = m_vStripLists[i].begin(); pos!=m_vStripLists[i].end() ; pos++) 00138 { 00139 pStrip=(*pos); 00140 ASSERTP(pStrip,"CListContour::InitMemory::1"); 00141 00142 pStrip->clear(); 00143 delete pStrip; 00144 } 00145 m_vStripLists[i].clear(); 00146 } 00147 } 00148 else 00149 m_vStripLists.resize(GetNPlanes()); 00150 } 00151 00152 inline void CListContour::CleanMemory() 00153 { 00154 CContour::CleanMemory(); 00155 00156 CLineStripList::iterator pos; 00157 CLineStrip* pStrip; 00158 UINT i; 00159 00160 // reseting lists 00161 for (i=0;i<m_vStripLists.size();i++) //G.Barrand 00162 { 00163 for (pos=m_vStripLists[i].begin(); pos!=m_vStripLists[i].end();pos++) 00164 { 00165 pStrip=(*pos); 00166 ASSERTP(pStrip,"CListContour::CleanMemory"); 00167 pStrip->clear(); 00168 delete pStrip; 00169 } 00170 m_vStripLists[i].clear(); 00171 } 00172 } 00173 00174 inline void CListContour::ExportLine(int iPlane,int x1, int y1, int x2, int y2) 00175 { 00176 ASSERT(iPlane>=0,"CListContour::ExportLine::0"); 00177 ASSERT(iPlane<(int)GetNPlanes(),"CListContour::ExportLine::1"); 00178 00179 // check that the two points are not at the beginning or end of the some line strip 00180 UINT i1=y1*(m_iColSec+1)+x1; 00181 UINT i2=y2*(m_iColSec+1)+x2; 00182 00183 CLineStrip* pStrip; 00184 00185 CLineStripList::iterator pos; 00186 bool added = false; 00187 for(pos=m_vStripLists[iPlane].begin(); pos!=m_vStripLists[iPlane].end() && !added; pos++) 00188 { 00189 pStrip=(*pos); 00190 ASSERTP(pStrip,"CListContour::ExportLine::2"); 00191 // check if points are appendable to this strip 00192 if (i1==pStrip->front()) 00193 { 00194 pStrip->insert(pStrip->begin(),i2); 00195 return; 00196 } 00197 if (i1==pStrip->back()) 00198 { 00199 pStrip->insert(pStrip->end(),i2); 00200 return; 00201 } 00202 if (i2==pStrip->front()) 00203 { 00204 pStrip->insert(pStrip->begin(),i1); 00205 return; 00206 } 00207 if (i2==pStrip->back()) 00208 { 00209 pStrip->insert(pStrip->end(),i1); 00210 return; 00211 } 00212 } 00213 00214 // segment was not part of any line strip, creating new one 00215 pStrip=new CLineStrip; 00216 pStrip->insert(pStrip->begin(),i1); 00217 pStrip->insert(pStrip->end(),i2); 00218 m_vStripLists[iPlane].insert(m_vStripLists[iPlane].begin(),pStrip); 00219 } 00220 00221 inline bool CListContour::ForceMerge(CLineStrip* pStrip1, CLineStrip* pStrip2,double aHeight) 00222 { 00223 00224 CLineStrip::iterator pos; 00225 CLineStrip::reverse_iterator rpos; 00226 00227 if (pStrip2->empty()) 00228 return false; 00229 00230 double x[4], y[4], weldDist; 00231 int index; 00232 index = pStrip1->front(); 00233 x[0] = GetXi(index); 00234 y[0] = GetYi(index); 00235 index = pStrip1->back(); 00236 x[1] = GetXi(index); 00237 y[1] = GetYi(index); 00238 index = pStrip2->front(); 00239 x[2] = GetXi(index); 00240 y[2] = GetYi(index); 00241 index = pStrip2->back(); 00242 x[3] = GetXi(index); 00243 y[3] = GetYi(index); 00244 00245 weldDist = 10*(m_dDx*m_dDx+m_dDy*m_dDy); 00246 00247 if (((x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2])< weldDist) 00248 || SpecialCompactStripCase(x[1],x[2],y[1],y[2],aHeight)) // L.Garnier 00249 00250 { 00251 for (pos=pStrip2->begin(); pos!=pStrip2->end();pos++) 00252 { 00253 index=(*pos); 00254 if(!ASSERT_RET(index>=0,"CListContour::ForceMerge::0")) return false; 00255 pStrip1->insert(pStrip1->end(),index); 00256 } 00257 pStrip2->clear(); 00258 return true; 00259 } 00260 00261 if (((x[3]-x[0])*(x[3]-x[0])+(y[3]-y[0])*(y[3]-y[0])< weldDist) 00262 || SpecialCompactStripCase(x[3],x[0],y[3],y[0],aHeight)) // L.Garnier 00263 { 00264 for (rpos=pStrip2->rbegin(); rpos!=pStrip2->rend();rpos++) 00265 { 00266 index=(*rpos); 00267 if(!ASSERT_RET(index>=0,"CListContour::ForceMerge::1")) return false; 00268 pStrip1->insert(pStrip1->begin(),index); 00269 } 00270 pStrip2->clear(); 00271 return true; 00272 } 00273 00274 if (((x[1]-x[3])*(x[1]-x[3])+(y[1]-y[3])*(y[1]-y[3])< weldDist) 00275 || SpecialCompactStripCase(x[1],x[3],y[1],y[3],aHeight)) // L.Garnier 00276 { 00277 for (rpos=pStrip2->rbegin(); rpos!=pStrip2->rend();rpos++) 00278 { 00279 index=(*rpos); 00280 if(!ASSERT_RET(index>=0,"CListContour::ForceMerge::2")) return false; 00281 pStrip1->insert(pStrip1->end(),index); 00282 } 00283 pStrip2->clear(); 00284 return true; 00285 } 00286 00287 if (((x[0]-x[2])*(x[0]-x[2])+(y[0]-y[2])*(y[0]-y[2])< weldDist) 00288 || SpecialCompactStripCase(x[0],x[2],y[0],y[2],aHeight)) // L.Garnier 00289 { 00290 for (pos=pStrip2->begin(); pos!=pStrip2->end();pos++) 00291 { 00292 index=(*pos); 00293 if(!ASSERT_RET(index>=0,"CListContour::ForceMerge::3")) return false; 00294 pStrip1->insert(pStrip1->begin(),index); 00295 } 00296 pStrip2->clear(); 00297 return true; 00298 } 00299 00300 return false; 00301 } 00302 00303 inline bool CListContour::MergeStrips(CLineStrip* pStrip1, CLineStrip* pStrip2) 00304 { 00305 CLineStrip::iterator pos; 00306 CLineStrip::reverse_iterator rpos; 00307 if (pStrip2->empty()) 00308 return false; 00309 00310 int index; 00311 00312 // debugging stuff 00313 if (pStrip2->front()==pStrip1->front()) 00314 { 00315 // retreiving first element 00316 pStrip2->pop_front(); 00317 // adding the rest to strip1 00318 for (pos=pStrip2->begin(); pos!=pStrip2->end();pos++) 00319 { 00320 index=(*pos); 00321 if(!ASSERT_MERGE_RET(index>=0,"CListContour::MergeStrips::0",pStrip2)) return false; 00322 pStrip1->insert(pStrip1->begin(),index); 00323 } 00324 pStrip2->clear(); 00325 return true; 00326 } 00327 00328 if (pStrip2->front()==pStrip1->back()) 00329 { 00330 pStrip2->pop_front(); 00331 // adding the rest to strip1 00332 for (pos=pStrip2->begin(); pos!=pStrip2->end();pos++) 00333 { 00334 index=(*pos); 00335 if(!ASSERT_MERGE_RET(index>=0,"CListContour::MergeStrips::1",pStrip2)) return false; 00336 pStrip1->insert(pStrip1->end(),index); 00337 } 00338 pStrip2->clear(); 00339 return true; 00340 } 00341 00342 if (pStrip2->back()==pStrip1->front()) 00343 { 00344 pStrip2->pop_back(); 00345 // adding the rest to strip1 00346 for (rpos=pStrip2->rbegin(); rpos!=pStrip2->rend();rpos++) 00347 { 00348 index=(*rpos); 00349 if(!ASSERT_MERGE_RET(index>=0,"CListContour::MergeStrips::2",pStrip2)) return false; 00350 pStrip1->insert(pStrip1->begin(),index); 00351 } 00352 pStrip2->clear(); 00353 return true; 00354 } 00355 00356 if (pStrip2->back()==pStrip1->back()) 00357 { 00358 pStrip2->pop_back(); 00359 // adding the rest to strip1 00360 for (rpos=pStrip2->rbegin(); rpos!=pStrip2->rend();rpos++) 00361 { 00362 index=(*rpos); 00363 if(!ASSERT_MERGE_RET(index>=0,"CListContour::MergeStrips::3",pStrip2)) return false; 00364 pStrip1->insert(pStrip1->end(),index); 00365 } 00366 pStrip2->clear(); 00367 return true; 00368 } 00369 00370 return false; 00371 } 00372 00373 inline bool CListContour::CompactStrips() 00374 { 00375 CLineStrip* pStrip; 00376 CLineStrip* pStripBase; 00377 UINT i; 00378 CLineStripList::iterator pos,pos2; 00379 CLineStripList newList; 00380 bool again, changed; 00381 00382 const double weldDist = 10*(m_dDx*m_dDx+m_dDy*m_dDy); 00383 00384 if(!ASSERT_RET(m_vStripLists.size() == GetNPlanes(),"CListContour::CompactStrips::0")) return false; 00385 for (i=0;i<GetNPlanes();i++) 00386 { 00387 double planeHeight = GetPlane(i); 00388 again=true; 00389 while(again) 00390 { 00391 // REPEAT COMPACT PROCESS UNTILL LAST PROCESS MAKES NO CHANGE 00392 00393 again=false; 00394 // building compacted list 00395 if(!ASSERT_RET(newList.empty(),"CListContour::CompactStrips::1")) return false; 00396 for (pos=m_vStripLists[i].begin(); pos!=m_vStripLists[i].end();pos++) 00397 { 00398 pStrip=(*pos); 00399 for (pos2=newList.begin(); pos2!=newList.end();pos2++) 00400 { 00401 pStripBase=(*pos2); 00402 changed=MergeStrips(pStripBase,pStrip); 00403 if (changed) 00404 again=true; 00405 if (pStrip->empty()) 00406 break; 00407 } 00408 if (pStrip->empty()) 00409 delete pStrip; 00410 else 00411 newList.insert(newList.begin(),pStrip); 00412 } 00413 00414 00415 // deleting old list 00416 m_vStripLists[i].clear(); 00417 CLineStrip* pStrip2; 00418 // Copying all 00419 for (pos2=newList.begin(); pos2 != newList.end(); pos2++) 00420 { 00421 pStrip2=(*pos2); 00422 CLineStrip::iterator pos1 = pStrip2->begin(),pos3; 00423 while (pos1!=pStrip2->end()) 00424 { 00425 pos3 = pos1; 00426 pos3++; 00427 if ( (*pos1) == (*pos3)) 00428 { 00429 if ( (*pos3) != (*pStrip2->end())) 00430 pStrip2->erase(pos3); 00431 else 00432 { 00433 pStrip2->erase(pos3); 00434 break; 00435 } 00436 } 00437 else 00438 pos1++; 00439 } 00440 00441 //if (!(pStrip2->front()==pStrip2->back() && pStrip2->size()==2)) 00442 if (pStrip2->size()!=1) 00443 m_vStripLists[i].insert(m_vStripLists[i].begin(),pStrip2 ); 00444 else 00445 delete pStrip2; 00446 } 00447 // emptying temp list 00448 newList.clear(); 00449 00450 } // OF WHILE(AGAIN) (LAST COMPACT PROCESS MADE NO CHANGES) 00451 00452 00453 if (m_vStripLists[i].empty()) 00454 continue; 00456 // compact more 00457 int Nstrip,j,index,count; 00458 00459 Nstrip = m_vStripLists[i].size(); 00460 std::vector<bool> closed(Nstrip); 00461 double x,y; 00462 00463 // First let's find the open and closed lists in m_vStripLists 00464 for(pos2 = m_vStripLists[i].begin(), j=0, count=0; pos2 != m_vStripLists[i].end(); pos2++, j++) 00465 { 00466 pStrip = (*pos2); 00467 00468 // is it open ? 00469 if (pStrip->front() != pStrip->back()) 00470 { 00471 index = pStrip->front(); 00472 x = GetXi(index); y = GetYi(index); 00473 index = pStrip->back(); 00474 x -= GetXi(index); y -= GetYi(index); 00475 00476 // is it "almost closed" ? 00477 if ((x*x+y*y < weldDist) || 00478 SpecialCompactStripCase(GetXi(pStrip->front()), // L.Garnier 00479 GetXi(pStrip->back()), 00480 GetYi(pStrip->front()), 00481 GetYi(pStrip->back()), 00482 planeHeight)) 00483 { 00484 closed[j] = true; 00485 // close it !!! Added by L.Garnier 00486 pStrip->push_back(pStrip->front()); 00487 // 00488 } 00489 else 00490 { 00491 closed[j] = false; 00492 // updating not closed counter... 00493 count ++; 00494 } 00495 } 00496 else 00497 closed[j] = true; 00498 } 00499 00500 // is there any open strip ? 00501 if (count > 1) 00502 { 00503 // Merge the open strips into NewList 00504 pos = m_vStripLists[i].begin(); 00505 for(j=0;j<Nstrip;j++) 00506 { 00507 if (closed[j] == false ) 00508 { 00509 pStrip = (*pos); 00510 newList.insert(newList.begin(),pStrip); 00511 pos = m_vStripLists[i].erase(pos); 00512 } 00513 else 00514 pos ++; 00515 } 00516 00517 // are they open strips to process ? 00518 while(newList.size()>1) 00519 { 00520 pStripBase = newList.front(); 00521 00522 // merge the rest to pStripBase 00523 again = true; 00524 while (again) 00525 { 00526 again = false; 00527 pos = newList.begin(); 00528 for(pos++; pos!=newList.end();) 00529 { 00530 pStrip = (*pos); 00531 changed = ForceMerge(pStripBase,pStrip,planeHeight); 00532 if (changed) 00533 { 00534 again = true; 00535 delete pStrip; 00536 pos = newList.erase(pos); 00537 } 00538 else 00539 pos ++; 00540 } 00541 } // while(again) 00542 00543 index = pStripBase->front(); 00544 x = GetXi(index); y = GetYi(index); 00545 index = pStripBase->back(); 00546 x -= GetXi(index); y -= GetYi(index); 00547 // if pStripBase is closed or not 00548 00549 if ((x*x+y*y < weldDist) || 00550 SpecialCompactStripCase(GetXi(pStripBase->front()), // L.Garnier 00551 GetXi(pStripBase->back()), 00552 GetYi(pStripBase->front()), 00553 GetYi(pStripBase->back()), 00554 planeHeight)) 00555 { 00556 00557 // close it !!! Added by L.Garnier 00558 if ((x!=0) || (y!=0)) { 00559 pStripBase->push_back(pStripBase->front()); 00560 } 00561 // 00562 m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); 00563 newList.pop_front(); 00564 } 00565 else 00566 { 00567 if (OnBoundary(pStripBase)) 00568 { 00569 TRACE(_TT("# open strip ends on boundary, continue.\n")); 00570 m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); 00571 newList.pop_front(); 00572 } 00573 else 00574 { 00575 PROBLEM(_TT("unpaird open strip at 1!\n")); 00576 //exit(0); 00577 return false; 00578 } 00579 } 00580 } // while(newList.size()>1); 00581 00582 00583 if (newList.size() ==1) 00584 { 00585 pStripBase = newList.front(); 00586 index = pStripBase->front(); // L.Garnier 00587 x = GetXi(index); y = GetYi(index); // L.Garnier 00588 index = pStripBase->back(); // L.Garnier 00589 x -= GetXi(index); y -= GetYi(index); // L.Garnier 00590 00591 // is it "almost closed", give last chance...5*weldDist 00592 if (x*x+y*y < 3*weldDist) // L.Garnier 00593 { 00594 m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); 00595 newList.pop_front(); 00596 } 00597 else if (OnBoundary(pStripBase)) 00598 { 00599 TRACE(_TT("# open strip ends on boundary, continue.\n")); 00600 m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); 00601 newList.pop_front(); 00602 } 00603 else 00604 { 00605 PROBLEM(_TT("unpaird open strip at 2!\n")); 00606 DumpPlane(i); 00607 //exit(0); 00608 return false; 00609 } 00610 } 00611 00612 newList.clear(); 00613 00614 } 00615 else if (count == 1) 00616 { 00617 pos = m_vStripLists[i].begin(); 00618 for(j=0;j<Nstrip;j++) 00619 { 00620 if (closed[j] == false ) 00621 { 00622 pStripBase = (*pos); 00623 break; 00624 } 00625 pos ++; 00626 } 00627 index = pStripBase->front(); // L.Garnier 00628 x = GetXi(index); y = GetYi(index); // L.Garnier 00629 index = pStripBase->back(); // L.Garnier 00630 x -= GetXi(index); y -= GetYi(index); // L.Garnier 00631 00632 // is it "almost closed", give last chance...5*weldDist 00633 if (x*x+y*y < 2*weldDist) // L.Garnier 00634 { 00635 //close it!! 00636 pStripBase->push_back(pStripBase->front()); // L.Garnier 00637 } 00638 else if (OnBoundary(pStripBase)) 00639 { 00640 TRACE(_TT("# open strip ends on boundary, continue.\n")); 00641 pStripBase->push_back(pStripBase->front()); // L.Garnier 00642 } 00643 else 00644 { 00645 TRACE(_TT("unpaird open strip at 3!")); 00646 DumpPlane(i); 00647 return false; // L.Garnier 00648 //exit(0); 00649 } 00650 newList.clear(); // L.Garnier 00651 } 00652 } 00653 return true; 00654 } 00655 00656 00657 inline bool CListContour::OnBoundary(CLineStrip* pStrip) 00658 { 00659 bool e1,e2; 00660 00661 int index = pStrip->front(); 00662 double x = GetXi(index), y = GetYi(index); 00663 if (x==m_pLimits[0] || x == m_pLimits[1] || 00664 y == m_pLimits[2] || y == m_pLimits[3]) 00665 e1 = true; 00666 else 00667 e1 = false; 00668 00669 index = pStrip->back(); 00670 x = GetXi(index); y = GetYi(index); 00671 if (x==m_pLimits[0] || x == m_pLimits[1] || 00672 y == m_pLimits[2] || y == m_pLimits[3]) 00673 e2 = true; 00674 else 00675 e2 = false; 00676 00677 return (e1 && e2); 00678 } 00679 00680 inline void CListContour::DumpPlane(UINT iPlane) const 00681 { 00682 CLineStripList::const_iterator pos; 00683 UINT i; 00684 CLineStrip* pStrip; 00685 00686 /*ASSERT(iPlane>=0,"CListContour::DumpPlane");*/ 00687 ASSERT(iPlane<GetNPlanes(),"CListContour::DumpPlane::0"); 00688 TRACE(_TT("Level : %d"),GetPlane(iPlane)); 00689 00690 TRACE(_TT("Number of strips : %d\r\n"),m_vStripLists[iPlane].size()); 00691 TRACE(_TT("i np start end xstart ystart xend yend\r\n")); 00692 for (pos = m_vStripLists[iPlane].begin(), i=0; pos != m_vStripLists[iPlane].end(); pos++, i++) 00693 { 00694 pStrip=*pos; 00695 ASSERTP(pStrip,"CListContour::DumpPlane::1"); 00696 TRACE(_TT("%d %d %d %d %g %g %g %g\r\n"),i,pStrip->size(),pStrip->front(),pStrip->back(), 00697 GetXi(pStrip->front()),GetYi(pStrip->front()), 00698 GetXi(pStrip->back()),GetYi(pStrip->back()) ); 00699 } 00700 } 00701 00702 inline double CListContour::Area(CLineStrip* Line) 00703 { 00704 // if Line is not closed, return 0; 00705 00706 double Ar = 0, x, y, x0,y0,x1, y1; 00707 int index; 00708 00709 CLineStrip::iterator pos; 00710 pos = Line->begin(); 00711 index = (*pos); 00712 x0 = x = GetXi(index); 00713 y0 = y = GetYi(index); 00714 00715 pos ++; 00716 00717 for(;pos!=Line->end();pos++) 00718 { 00719 index = (*pos); 00720 x1 = GetXi(index); 00721 y1 = GetYi(index); 00722 // Ar += (x1-x)*(y1+y); 00723 Ar += (y1-y)*(x1+x)-(x1-x)*(y1+y); 00724 x = x1; 00725 y = y1; 00726 00727 } 00728 00729 00730 //Ar += (x0-x)*(y0+y); 00731 Ar += (y0-y)*(x0+x)-(x0-x)*(y0+y); 00732 // if not closed curve, return 0; 00733 if ((x0-x)*(x0-x) + (y0-y)*(y0-y)>20*(m_dDx*m_dDx+m_dDy*m_dDy)) 00734 { 00735 Ar = 0; 00736 TRACE(_TT("# open curve!\n")); 00737 } 00738 //else Ar /= -2; 00739 else Ar/=4; 00740 // result is \int ydex/2 alone the implicit direction. 00741 return Ar; 00742 } 00743 00744 inline double CListContour:: EdgeWeight(CLineStrip* pLine, double R) 00745 { 00746 CLineStrip::iterator pos; 00747 int count = 0,index; 00748 double x,y; 00749 for(pos = pLine->begin(); pos!=pLine->end(); pos++) 00750 { 00751 index = (*pos); 00752 x = GetXi(index); 00753 y = GetYi(index); 00754 if (fabs(x) > R || fabs(y) > R) 00755 count ++; 00756 } 00757 return (double)count/pLine->size(); 00758 } 00759 00760 inline bool CListContour::PrintContour(std::ostream& a_out) 00761 { 00762 std::streamsize old_prec = a_out.precision(3); 00763 a_out << std::setprecision(10); 00764 00765 UINT i, index; 00766 CLineStrip* pStrip; 00767 CLineStrip::iterator pos2; 00768 CLineStripList::iterator pos; 00769 00770 for(i=0;i<GetNPlanes();i++) { 00771 for(pos = m_vStripLists[i].begin();pos!=m_vStripLists[i].end();pos++) 00772 { 00773 pStrip = (*pos); 00774 for(pos2 = pStrip->begin();pos2!=pStrip->end();pos2++) 00775 { 00776 index = (*pos2); 00777 a_out << GetXi(index)<<"\t"<<GetYi(index)<<"\n"; 00778 } 00779 a_out<<"\n"; 00780 } 00781 } 00782 a_out.precision(old_prec); 00783 return true; 00784 00785 } 00786 00787 //G.Barrand : from .h to .cxx to avoid ASSERT in .h 00788 inline CLineStripList* CListContour::GetLines(unsigned int iPlane) { 00789 /*ASSERT(iPlane>=0);*/ 00790 ASSERT(iPlane<GetNPlanes(),"CListContour::GetLines"); 00791 return &m_vStripLists[iPlane]; 00792 } 00793 00794 // Added by L.Garnier 00795 inline bool CListContour::SpecialCompactStripCase(double aXfront,double aXback,double aYfront,double aYback,double actualHeight) 00796 { 00797 // To solve the case of a list of strips 00798 // which appeared to be open but should correspond to a closed 00799 // contour. 00800 // With the today Generate() algorithm, it appears that we fall 00801 // on this case when the begin and end points 00802 // are on a horizontal or vertical line. 00803 // (case where front()->x == back()->x or front()->y == back()->y). 00804 // We try to detect in this method this situation and decide to close 00805 // or not the line. To do that we check the heigth of intermediate 00806 // points to see if there are on the same contour; if so we close 00807 // the line (and return true), if not we do nothing (and return false). 00808 00809 // check if we could realy close it 00810 float marge = 1; // *m_dDy or *m_dDx. 1 seems to be good and normal, but why 00811 // not 2 in certain cases??? 00812 00813 double distToNext =0; 00814 // try to get the correct hight 00815 if (GetPlane(0)>= actualHeight) { 00816 return false; 00817 } 00818 if (GetNPlanes() >1){ 00819 distToNext = GetPlane(1)-GetPlane(0); 00820 } else { 00821 return false; 00822 } 00823 00824 if ((aYback-aYfront) == 0) { 00825 double temp; 00826 double av; 00827 double eg; 00828 double ap; 00829 00830 if (aXfront==m_pLimits[0] && aXback == m_pLimits[1]) return false; 00831 if (aXfront==m_pLimits[1] && aXback == m_pLimits[0]) return false; 00832 00833 if (aXfront > aXback ) { 00834 temp = aXfront; 00835 aXfront = aXback; 00836 aXback = temp; 00837 } 00838 for(double check=aXfront+m_dDx; 00839 check<aXback; 00840 check+=m_dDx) { 00841 av = ((*m_pFieldFcn)(check,aYback-marge*m_dDy,m_pFieldFcnData)-actualHeight); 00842 eg = ((*m_pFieldFcn)(check,aYback,m_pFieldFcnData)-actualHeight); 00843 ap = ((*m_pFieldFcn)(check,aYback+marge*m_dDy,m_pFieldFcnData)-actualHeight); 00844 00845 if ((av>distToNext) && (ap>distToNext) && (eg>distToNext)) { 00846 return false; 00847 } else if ((av<0) && (ap<0) && (eg<0)) { 00848 return false; 00849 } 00850 } 00851 return true; 00852 } else if ((aXback-aXfront) == 0) { 00853 double temp; 00854 double av; 00855 double eg; 00856 double ap; 00857 if (aYfront==m_pLimits[3] && aYback == m_pLimits[2]) return false; 00858 if (aYfront==m_pLimits[2] && aYback == m_pLimits[3]) return false; 00859 00860 if (aYfront > aYback ) { 00861 temp = aYfront; 00862 aYfront = aYback; 00863 aYback = temp; 00864 } 00865 00866 for(double check=aYfront+m_dDy; 00867 check<aYback; 00868 check+=m_dDy) { 00869 av = ((*m_pFieldFcn)(aXback-marge*m_dDx,check,m_pFieldFcnData)-actualHeight); 00870 eg = ((*m_pFieldFcn)(aXback,check,m_pFieldFcnData)-actualHeight); 00871 ap = ((*m_pFieldFcn)(aXback+marge*m_dDx,check,m_pFieldFcnData)-actualHeight); 00872 if ((av>distToNext) && (ap>distToNext) && (eg>distToNext)) { 00873 return false; 00874 } else if ((av<0) && (ap<0) && (eg<0)) { 00875 return false; 00876 } 00877 } 00878 return true; 00879 } 00880 return false; 00881 } 00882 00883 } 00884 00885 #endif