#include "Stdafx.h" #include "ClosedFinder.h" ////////////////////////////////////////////////////////////////////////// ClosedFinder::ClosedFinder(void) { tCurMaxSize = 0; } ClosedFinder::~ClosedFinder(void) { for (std::map::iterator pit =mPointsSrc.begin(); pit != mPointsSrc.end();++pit) { if(pit->second != NULL) { delete pit->second; pit->second = NULL; } } for (std::map::iterator pit =mArcsSrc.begin(); pit != mArcsSrc.end();++pit) { if(pit->second != NULL) { delete pit->second; pit->second = NULL; } } mPointsSrc.clear(); mArcsSrc.clear(); } bool ClosedFinder::getArcHalfEdgeBeginEnd(const std::list& lstEdge, const sPoint* & ptFist , const sPoint* & ptEnd) { if (!lstEdge.empty()) { //sArcHalfEdge::ArcHalfEdge_const_iterator itFirst(&(*lstEdge.begin())); //sArcHalfEdge::ArcHalfEdge_const_iterator itEnd(&(*lstEdge.rbegin())); ////ptFist = itFirst.First(); ////ptEnd = itEnd.GetEnd(); if(lstEdge.size() == 1) { sArcHalfEdge::ArcHalfEdge_const_iterator itFirst(&(*lstEdge.begin())); ptFist = itFirst.First(); ptEnd = itFirst.GetEnd(); } else { std::list::const_iterator iter = lstEdge.begin(); sArcHalfEdge::ArcHalfEdge_const_iterator itFirst(&(*iter++)); sArcHalfEdge::ArcHalfEdge_const_iterator itEnd(&(*iter)); const sPoint* sp1 = itFirst.First(); const sPoint* ep1 = itFirst.GetEnd(); const sPoint* sp2 = itEnd.First(); const sPoint* ep2 = itEnd.GetEnd(); if(sp1->m_Id == sp2->m_Id || sp1->m_Id == ep2->m_Id) { ptFist = ep1; ptEnd = sp1; } else if(ep1->m_Id == sp2->m_Id || ep1->m_Id == ep2->m_Id) { ptFist = sp1; ptEnd = ep1; } for(;iter != lstEdge.end(); iter++) { sArcHalfEdge::ArcHalfEdge_const_iterator it(&(*iter)); const sPoint* sp = it.First(); const sPoint* ep = it.GetEnd(); if(sp->m_Id != ptEnd->m_Id) { ptEnd = sp; } else { ptEnd = ep; } } } } return !lstEdge.empty(); } bool ClosedFinder::addPoint( Point_Key key, sPoint* pPoint, bool bCheck /*= true*/ ) { std::map::iterator it = mPointsSrc.find(key); if (it != mPointsSrc.end() && bCheck) { // ASSERT(0); } mPointsSrc[key] = pPoint; return true; } bool ClosedFinder::addArc( Arc_Key key , sArc* pArc , bool bCheck /*= true*/ ) { bool bRe = !pArc->mPoints.empty(); if (bRe) { //保存数据 std::map::iterator it = mArcsSrc.find(key); if (it != mArcsSrc.end() && bCheck) { //ASSERT(0); } // mArcsSrc[key] = pArc; //保存过端点的linkData { //起点的半边数据 sArcHalfEdge halfEdge(pArc); halfEdge.mDirection = EAD_Begin2End; // AddHaldEdge(halfEdge); //终点的半边数据 halfEdge.mDirection = EAD_End2Begin; // AddHaldEdge(halfEdge); } } return bRe; } void ClosedFinder::AddHaldEdge( const sArcHalfEdge &halfEdge ) { sArcHalfEdge::ArcHalfEdge_const_iterator itHalfEdge(&halfEdge); const sPoint* pt = itHalfEdge.First(); if (pt) { std::map* pData = getMapValue(mPointLinkData, pt->m_Id, true); if (pData) { (*pData) [halfEdge.mpArc->m_Id] = halfEdge; } } } //#define __LILIN_DEBUG_ #ifdef __LILIN_DEBUG_ #include #endif //搜索的最大多边形 #define STEPMAX 60 //生成多边形,返回值为多边形的个数 int ClosedFinder::GeneralPolygon() { mCurPolygon_Key = 1; //int MaxSizeArr[STEPMAX * 2/* + 1*/] = {0}; //{ // //MaxSizeArr[0] = 2; // for(int i = 0; i < STEPMAX; i++) // { // MaxSizeArr[2 * i/*+1*/] = 2 + i; //第一次 // MaxSizeArr[2*i + 1/*+1*/] = 2 + i; //第二次 // } //} #ifdef __LILIN_DEBUG_ time_t t = time( 0 ); char tmp[64]; strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A 本年第%j天 %z", localtime(&t) ); std::string str(tmp); #endif int count = 0; int lastCount = 2; count = GetMaxEdgeSet(); while(count > 0) { for(int i = lastCount; i < count + 1; i++) { tCurMaxSize = i; tmapGen.clear(); bool isExist = false; std::map >::iterator it = mPointLinkData.begin(); for(; it != mPointLinkData.end(); it++) { sPolygon polygon; std::map& linkDatas = it->second; bool bReture = __GeneralPolygon(polygon, linkDatas); if (bReture) { tmapGen[it->first] = it->first; isExist = true; } } if(isExist) { i--; } } lastCount = count +1; //itTmp = mPointLinkData.begin(); //std::map& linkDatas = itTmp->second; //count = SearchGeneralPolygon(polygonTmp, linkDatas); count = GetMaxEdgeSet(); if(lastCount > count) break; } //for(int i = 0; i < STEPMAX; i++) //{ // tCurMaxSize = i + 2; // tmapGen.clear(); // bool isExist = false; // // std::map >::iterator it = mPointLinkData.begin(); // for(; it != mPointLinkData.end(); it++) // { // sPolygon polygon; // // std::map& linkDatas = it->second; // // bool bReture = __GeneralPolygon(polygon, linkDatas); // // if (bReture) // { // tmapGen[it->first] = it->first; // isExist = true; // } // } // // if(isExist) // { // i--; // } //} //2012-5-21 srq 针对bug 网格线,当输入的数据不能创建面时,系统总非法退出,建议给提示信息。 注:交点少于2个是不可能成面的 if(mPolygons.size()<1) return 0; ClearMaxEdgePolygon(); __CombinPolygon(); #ifdef __LILIN_DEBUG_ { time_t t = time( 0 ); char tmp[64]; strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A 本年第%j天 %z", localtime(&t) ); std::string str1(tmp); str = str + str1; } AfxMessageBox(str); #endif return mPolygons.size(); } bool ClosedFinder::__GeneralPolygon(sPolygon polygon, std::map& linkDatas ) { bool bReturn = false; size_t iSize = polygon.mArcHalfEdge.size() + 1; std::multimap tmapHalfEdgebyTime = SortPointLinkEdge(linkDatas); Point_Key polyFirstId = 0; //当前的多边形弧段集合的起始点号 Arc_Key arcPreId = 0; //上一个ARC的ID if (!polygon.mArcHalfEdge.empty()) { sArcHalfEdge::ArcHalfEdge_const_iterator itArcHalfEdge(&(*polygon.mArcHalfEdge.begin())); polyFirstId = itArcHalfEdge.First()->m_Id; arcPreId = polygon.mArcHalfEdge.rbegin()->mpArc->m_Id; } std::multimap::const_iterator itLink = tmapHalfEdgebyTime.begin(); for(; itLink != tmapHalfEdgebyTime.end(); ++itLink) { sPolygon polygonCur(polygon); //创建临时多边形,防止污源被污染 // const sArcHalfEdge& halEdge = *itLink->second; const sArc *mpArc = halEdge.mpArc; if (arcPreId == mpArc->m_Id) {continue;} //不能为上一段线 // if (mpArc->mTimeofSearch == 2) { //此边及其以后的所有边为死边,返回(因为已经排过顺序) break; } else { sArcHalfEdge::ArcHalfEdge_const_iterator itArcHalfEdge(&halEdge); Point_Key ptFirstId = itArcHalfEdge.First()->m_Id; Point_Key ptEndId = itArcHalfEdge.GetEnd()->m_Id; if (tmapGen.find(polyFirstId) == tmapGen.end() && tmapGen.find(ptFirstId) == tmapGen.end()) //不为生成过的点 { if (iSize == tCurMaxSize) { //判断最后一点和第一点是否相等,是的话,则加入到结果封闭区域中 if (ptEndId == polyFirstId) { //恭喜,找到封闭的区域 //if (tCurMaxSize == 2) //TODO : 为两边的时候比较特殊 //{ //tmapGen[ptFirstId] = ptFirstId; //} AddEdge(polygonCur, halEdge); if(_AddPolygon(polygonCur)) { bReturn = true; break; } } else { //失败,不处理 } } else { if (polygonCur.ExistPoint(ptEndId)) { continue; //continue; } if (tCurMaxSize > 2 && polyFirstId == ptEndId) { continue; } //不满足最大边,得到最后一点,递归(深度优先) AddEdge(polygonCur, halEdge); //polygonCur.AddEdge(halEdge); std::map* pData = getMapValue(mPointLinkData, ptEndId, false); if (pData) { bReturn = __GeneralPolygon(polygonCur, *pData); if (bReturn) { break; } } else { // ASSERT(0); } } } } } return bReturn; } //搜索多边形, 返回多边形边数,没有 返回-1 int ClosedFinder::SearchGeneralPolygon(sPolygon polygon, std::map& linkDatas ) { bool bReturn = false; size_t iSize = polygon.mArcHalfEdge.size() + 1; std::multimap tmapHalfEdgebyTime = SortPointLinkEdge(linkDatas); Point_Key polyFirstId = 0; //当前的多边形弧段集合的起始点号 Arc_Key arcPreId = 0; //上一个ARC的ID if (!polygon.mArcHalfEdge.empty()) { sArcHalfEdge::ArcHalfEdge_const_iterator itArcHalfEdge(&(*polygon.mArcHalfEdge.begin())); polyFirstId = itArcHalfEdge.First()->m_Id; arcPreId = polygon.mArcHalfEdge.rbegin()->mpArc->m_Id; } std::multimap::const_iterator itLink = tmapHalfEdgebyTime.begin(); for(; itLink != tmapHalfEdgebyTime.end(); ++itLink) { sPolygon polygonCur(polygon); //创建临时多边形,防止污源被污染 // const sArcHalfEdge& halEdge = *itLink->second; const sArc *mpArc = halEdge.mpArc; if (arcPreId == mpArc->m_Id) {continue;} //不能为上一段线 // if (mpArc->mTimeofSearch == 2) { //此边及其以后的所有边为死边,返回(因为已经排过顺序) break; } else { sArcHalfEdge::ArcHalfEdge_const_iterator itArcHalfEdge(&halEdge); Point_Key ptFirstId = itArcHalfEdge.First()->m_Id; Point_Key ptEndId = itArcHalfEdge.GetEnd()->m_Id; if (tmapGen.find(polyFirstId) == tmapGen.end() && tmapGen.find(ptFirstId) == tmapGen.end()) //不为生成过的点 { //判断最后一点和第一点是否相等,是的话,则加入到结果封闭区域中 if (ptEndId == polyFirstId) { //恭喜,找到封闭的区域 //if (tCurMaxSize == 2) //TODO : 为两边的时候比较特殊 //{ //tmapGen[ptFirstId] = ptFirstId; //} AddEdge(polygonCur, halEdge); //return polygonCur.mArcHalfEdge.size(); polygonCur.CalMark(); if(tmapExistPolygon.find(polygonCur.mMarkType) == tmapExistPolygon.end()) { return polygonCur.mArcHalfEdge.size(); } } else { if (polygonCur.ExistPoint(ptEndId)) { int index = polygonCur.GetPointIndex(ptEndId); return polygonCur.mArcHalfEdge.size() - index + 1; //continue; } if (tCurMaxSize > 2 && polyFirstId == ptEndId) { continue; } //不满足最大边,得到最后一点,递归(深度优先) AddEdge(polygonCur, halEdge); //polygonCur.AddEdge(halEdge); std::map* pData = getMapValue(mPointLinkData, ptEndId, false); if (pData) { int count = SearchGeneralPolygon(polygonCur, *pData); if (count > 0) { return count; } } else { // ASSERT(0); } } } } } return -1; } int ClosedFinder::GetMaxEdgeSet() { int count = 0; int lastCount = 2; std::map >::iterator itTmp = mPointLinkData.begin(); for(; itTmp != mPointLinkData.end(); itTmp++) { sPolygon polygonTmp; std::map& linkDatas = itTmp->second; count = SearchGeneralPolygon(polygonTmp, linkDatas); if(count > 0) { return count; } } return count; } bool ClosedFinder::_AddPolygon( sPolygon &polygonCur) { polygonCur.m_Id = mCurPolygon_Key; polygonCur.CalMark(); // if(!(/*tCurMaxSize == 3 &&*/ ExistPolygon(polygonCur)))//没有存在多边形 { // 判断多边形的边是否都在 border中 yc 20130724 bool isAll = true; std::vector::iterator iter = polygonCur.mArcHalfEdge.begin(); for(; iter != polygonCur.mArcHalfEdge.end(); iter ++) { int i = 0; for(; i < (int)border.size(); i++) { if(border[i] == iter->mpArc->m_IdSrc) { break; } } if( i == (int)border.size()) { isAll = false; break; } } if(isAll) { return false; } mCurPolygon_Key++ ; //把多边形的边的计算数加1 #ifdef _DEBUG std::string str; #endif { #ifdef _DEBUG //str.Format(_T("(%d): "), polygonCur.m_Id); str = "(" + std::to_string(polygonCur.m_Id) + "): "; #endif std::vector::iterator itpl = polygonCur.mArcHalfEdge.begin(); polygonCur.mIsIland = true; for(; itpl != polygonCur.mArcHalfEdge.end(); itpl ++) { itpl->mpArc->mTimeofSearch += 1; //去掉孤岛标志 sArcHalfEdge& halfEdge = *itpl; PostIsland(polygonCur, halfEdge); #ifdef _DEBUG sArcHalfEdge::ArcHalfEdge_const_iterator halfIter(&(*itpl)); std::string strT; //strT.Format(_T("%d(%c,%d-%d), "), itpl->mpArc->m_Id, 'a' + itpl->mpArc->m_Id - 1, // halfIter.First()->m_Id, halfIter.GetEnd()->m_Id); char arcChar = 'a' + itpl->mpArc->m_Id - 1; strT = std::to_string(itpl->mpArc->m_Id) + "(" + arcChar + "," + std::to_string(halfIter.First()->m_Id) + "-" + std::to_string(halfIter.GetEnd()->m_Id) + "), "; str = str + strT; #endif } } //如果为孤岛,需要把孤岛的边再次加1,这样,就不会再次搜索 if (polygonCur.mIsIland) { std::vector::iterator itpl = polygonCur.mArcHalfEdge.begin(); for(; itpl != polygonCur.mArcHalfEdge.end(); itpl ++) { itpl->mpArc->mTimeofSearch += 1; } #ifdef _DEBUG str = str + "(island)"; #endif } mPolygons[polygonCur.m_Id] = polygonCur; #ifdef _DEBUG str = str + "\n"; //OutputDebugString(str.c_str()); #endif //缓存所有两变形面 _PostPolygon2edge(polygonCur); //AfxMessageBox(str); return true; } return false; } bool ClosedFinder::ExistPolygon( const sPolygon &polygonCur ) { bool bExist = false; std::map::const_iterator it = tmapExistPolygon.find(polygonCur.mMarkType); //已经被生成过的多边形, if (it != tmapExistPolygon.end())//存在 { bExist = true; } else { //缓存已经存在的东东 tmapExistPolygon[polygonCur.mMarkType] = polygonCur.m_Id; } return bExist; } void ClosedFinder::PostIsland( sPolygon &polygonCur, sArcHalfEdge& halfEdge ) { if (polygonCur.mIsIland) { sArcHalfEdge::ArcHalfEdge_const_iterator itHalfEdge(&(halfEdge)); const sPoint* pt = itHalfEdge.First(); const std::map*pDate = getMapValue_Const >(mPointLinkData, pt->m_Id); // if (pDate && pDate->size() > 2) //非孤岛 { polygonCur.mIsIland = false; } } } TimeofSearch ClosedFinder::_GetMaxTimeOfSearch( sPolygon &polygonCur) { TimeofSearch mTimeofSearch = 0; std::vector::const_iterator it = polygonCur.mArcHalfEdge.begin(); for(; it != polygonCur.mArcHalfEdge.end(); it++) { mTimeofSearch = max(it->mpArc->mTimeofSearch, mTimeofSearch); } return mTimeofSearch; } // std::multimap ClosedFinder::SortPointLinkEdge( std::map &linkDatas ) { std::multimap tmapHalfEdgebyTime; tmapHalfEdgebyTime.clear(); std::map::iterator itLink = linkDatas.begin(); for(; itLink != linkDatas.end(); itLink++) { TimeofSearch timesS = itLink->second.mpArc->mTimeofSearch; //tmapHalfEdgebyTime.insert(std::make_pair(timesS, &itLink->second)); //pj change tmapHalfEdgebyTime.insert(std::make_pair(timesS, &itLink->second)); } return tmapHalfEdgebyTime; } void ClosedFinder::_PostPolygon2edge(const sPolygon &polygonCur ) { //return; if (polygonCur.mArcHalfEdge.size() == 2) { CompositeKey compKey(0,0); if (polygonCur.GetBE_CompositeKey(compKey)) { //mp std::map >* pCompData = getMapValue > > (mmapLinkArcs2, compKey, true);; //弧段所属的等同段 if (pCompData) { polygonCur.GetBE_HalfEdge(*pCompData); } } } } void ClosedFinder::AddEdge( sPolygon &polygonCur, const sArcHalfEdge& halEdge ) { sArcHalfEdge halEdgeT(halEdge); //判断最后当前的半边数据结构是否存在两边形 if (!mmapLinkArcs2.empty() && !polygonCur.mArcHalfEdge.empty()) { sArcHalfEdge::ArcHalfEdge_const_iterator itHalf(&halEdgeT); CompositeKey compKey(0,0); compKey.mKey1 = min(itHalf.First()->m_Id, itHalf.GetEnd()->m_Id); compKey.mKey2 = max(itHalf.First()->m_Id, itHalf.GetEnd()->m_Id); // const std::map >* pCompData = getMapValue_Const > > (mmapLinkArcs2, compKey);; //弧段所属的等同段 //存在,求最小的距离 if (pCompData) { //std::map >::const_iterator& itArcs = pCompData->find(compKey.mKey1); //pj auto itArcs = pCompData->find(compKey.mKey1); if (itArcs != pCompData->end()) { const std::map& arcs = itArcs->second; std::map tHalfByDis; gp_Point pt(0,0,0); polygonCur.GetAverageMarkPoint(pt); { std::map::const_iterator it = arcs.begin(); for(; it != arcs.end(); it++) { const gp_Point& ptCur = it->second.mpArc->mMarkPoint; double dbl = (pt.X() - ptCur.X())*((pt.X() - ptCur.X())) + (pt.Y() - ptCur.Y())*(pt.Y() - ptCur.Y()) + (pt.Z() - ptCur.Z()) * (pt.Z() - ptCur.Z()); tHalfByDis[dbl] = &it->second; } } // if (!tHalfByDis.empty()) { std::map::const_iterator it = tHalfByDis.begin(); for(; it != tHalfByDis.end(); it ++) { const sArcHalfEdge* psArcHalfEdge = it->second; if (psArcHalfEdge->mpArc->mTimeofSearch < 2 && !polygonCur.ExistArc(psArcHalfEdge->mpArc->m_Id)) { halEdgeT = * it->second; break; } } } } } } //添加 polygonCur.AddEdge(halEdgeT); } bool ClosedFinder::__CombinPolygon() { // std::map::const_iterator itpl = mPolygons.begin(); for(; itpl != mPolygons.end(); itpl++) { const sPolygon& pl = itpl->second; const std::vector& mArcHalfEdge = pl.mArcHalfEdge; if (!mArcHalfEdge.empty()) { std::list > >& lstPolygon = *getMapValue > > >(mPolygonsCombin, itpl->first, true); std::pair > pairEdge; std::vector::const_iterator it = mArcHalfEdge.begin(); // const sArcHalfEdge* edgeSrc = &(*it++); pairEdge.first = edgeSrc->mpArc->m_IdSrc; pairEdge.second.push_back(*edgeSrc); for(; it != mArcHalfEdge.end(); it++) { const sArcHalfEdge* edgeCur = &(*it); if (edgeCur->mpArc->m_IdSrc == pairEdge.first) { pairEdge.second.push_back(*edgeCur); } else { lstPolygon.push_back(pairEdge); // edgeSrc = edgeCur; pairEdge.first = edgeSrc->mpArc->m_IdSrc; pairEdge.second.clear(); pairEdge.second.push_back(*edgeSrc); } } //尾首合并 //--- yangchen 2012.5.15 start std::pair > pairEdgeTmp = lstPolygon.front(); if(pairEdgeTmp.first == pairEdge.first) { std::list edgeSet = pairEdge.second; std::list edgeSetTmp = pairEdgeTmp.second; for(std::list::reverse_iterator iter = edgeSet.rbegin(); iter != edgeSet.rend(); iter++) { pairEdgeTmp.second.push_front(*iter); } lstPolygon.pop_front(); lstPolygon.push_front(pairEdgeTmp); } else //--- yangchen 2012.5.15 end lstPolygon.push_back(pairEdge); } } return true; } bool ClosedFinder::ClearMaxEdgePolygon() { std::map::reverse_iterator itpl = mPolygons.rbegin(); sPolygon pl = itpl->second; Polygon_Key ikey = itpl->first; vector keySet1 = pl.GetPointKeySet(); //CompositeKey ckey; //pl.GetBE_CompositeKey(ckey); itpl++; for (;itpl!=mPolygons.rend();++itpl) { if(IsIncludeClosedPolygon(keySet1,itpl->second.GetPointKeySet())) { mPolygons.erase(ikey); break; } } return true; } bool ClosedFinder::IsIncludeClosedPolygon(vector& keySet1, vector keySet2) { int count = 0; for(vector::iterator iter1 = keySet1.begin();iter1 != keySet1.end(); iter1++) { for(vector::iterator iter2 = keySet2.begin();iter2 != keySet2.end(); iter2++) { if(*iter1 == *iter2) { count++; break; } } } return count > 2; }