#include "StdAfx.h" #include #include "XCoverVisibleRelationCal.h" #include "XCurveInline.h" #include #include "SectionUtility.h" #include "XGlobalFunc.h" #define SET_LINE_PT(line, pt1, pt2)\ line.SetStartPoint(pt1);\ line.SetEndPoint(pt2) namespace { int GetPointPosInPoly2d(const XPoly2D &poly, const XPoint &pt) { for (int i = 0; i < poly.Length(); ++i) { if (pt == poly[i]) return i; } return -1; } bool IsIntersection(const XPoly2D &Low, const XPoly2D &Top) { for (int i = 0; i < SectionUtility::GetCountOfSegmentForPoly(Low)/*Low.TotalSegments()*/; ++i) { XCurveSegment segLow = SectionUtility::GetSegmentOfPoly(Low, i); /*Low.Nth(i, segLow);*/ for (int j = 0; j < SectionUtility::GetCountOfSegmentForPoly(Top)/*Top.TotalSegments()*/; ++j) { XCurveSegment segTop = SectionUtility::GetSegmentOfPoly(Top, j); // Top.Nth(j, segTop); XPoint pt; if (segLow.Intersection(segTop, pt, pt)) return true; } } return false; } XCoverVisibleRelationCal::SectionRelative CanCover(const XPoly2D &Low, const XPoly2D &Top) { if (IsIntersection(Low, Top)) return XCoverVisibleRelationCal::kIntersection; if (SectionUtility::GetCountOfSegmentForPoly(Top)/*Top.TotalSegments()*/ == 1) // 如果top面只有一根曲线,则不用计算遮挡关系 return XCoverVisibleRelationCal::kLowContainTop; if (PR_OUTSIDE != (Top[0] & Low)) // 如top面的顶点有一点在low 面内,则low面包含top面 return XCoverVisibleRelationCal::kLowContainTop; else if (PR_OUTSIDE != (Low[0] & Top)) // 如low面的顶点有一点在top 面内,则top面包含low面 return XCoverVisibleRelationCal::kTopContainLow; else // 两个面的顶点都在对方的外面,则互不包含 return XCoverVisibleRelationCal::kNoneIntersection; } bool IsCoverBlockRef(const std::vector &records, XSectionFill &fill, const std::vector &fills) { BlockRefInfo block; fill.GetBlockRefInfo(block); XPoly2D poly = block.ToPoly2D(); // 判断与 投影结果 的遮挡关系 for (size_t i = 0; i < records.size(); ++i) { // 判断与 投影面的距离 的大小,如record曲线大于fill曲线的,则说明 record的曲线在 fill曲线后面 // 则不进行遮挡判断 if (records[i].GetElevation() <= block.m_dHeight) continue; XCoverVisibleRelationCal::SectionRelative rela = CanCover(poly, records[i].GetOriginalPoly()); // fill 曲线 包含 record 曲线 或 两曲线完全不包含 if (rela == XCoverVisibleRelationCal::kLowContainTop || rela == XCoverVisibleRelationCal::kNoneIntersection) continue; else return true; } // 判断与 其它 添充对象的遮挡关系 for (int i = 0; i < fills.size(); ++i) { for (int k = 0; k < fills[i].length(); ++k) { XSectionFill *pFill = (XSectionFill*)fills[i][k]; BlockRefInfo _block; pFill->GetBlockRefInfo(_block); if (_block.m_dHeight <= block.m_dHeight) continue; XPoly2D _poly = _block.ToPoly2D(); XCoverVisibleRelationCal::SectionRelative rela = CanCover(poly, _poly); // fill 曲线 包含 record 曲线 或 两曲线完全不包含 if (rela == XCoverVisibleRelationCal::kLowContainTop || rela == XCoverVisibleRelationCal::kNoneIntersection) continue; else return true; } } return false; } // 返回1 两个交点,返回2 一个交点 int Intersection(const XLine &line, const XPoly2D &poly, XPoint &pt1, XPoint &pt2) { XPoly2D tmp; for (int i = 0; i < SectionUtility::GetCountOfSegmentForPoly(poly)/*poly.TotalSegments()*/; ++i) { XPoint pt; XCurveSegment seg = SectionUtility::GetSegmentOfPoly(poly, i); /*poly.Nth(i, seg);*/ if (seg.Intersection(line, pt, pt)) { if (!tmp.FindPoint(pt)) tmp.AppendNode(pt); } } if (tmp.Length() == 2) { pt1 = *tmp[0]; pt2 = *tmp[1]; return 2; } if (tmp.Length() == 1) { pt1 = *tmp[0]; return 1; } return 0; } bool JudgeRelationForLineAndPolyLine(const XLine &line, const XPoly2D &poly, std::vector &show, std::vector &hide) { XPoint ptS = line.GetStartPoint(), ptE = line.GetEndPoint(); int posS = ptS & poly, posE = ptE & poly; // 直线在闭合曲线内(两点都在内,或一个在内,一个在边上,或都在边上) if ((posS == posE && posS == PR_INSIDE) || (posS == PR_EDGE && posE == PR_INSIDE) || (posS == PR_INSIDE && posE == PR_EDGE) || (posS == posE && posS == PR_EDGE)) { hide.push_back(line); return false; } XPoint pt1, pt2; int nInter = Intersection(line, poly, pt1, pt2); // 直线在闭合曲线外(两点都在外(且与曲线无交点).或一个在外,一个在边上) if ((posS == posE && posS == PR_OUTSIDE && nInter < 2) || (posS == PR_EDGE && posE == PR_OUTSIDE && nInter == 1) || (posS == PR_OUTSIDE && posE == PR_EDGE && nInter == 1)) { show.push_back(line); return true; } if (nInter == 2) { hide.push_back(XLine(pt1, pt2, LS_FINITE)); if (posS == PR_OUTSIDE && posE == PR_OUTSIDE) { if (ptS.Distance(pt1) > ptS.Distance(pt2)) { show.push_back(XLine(ptS, pt2, LS_FINITE)); show.push_back(XLine(pt1, ptE, LS_FINITE)); } else { show.push_back(XLine(ptS, pt1, LS_FINITE)); show.push_back(XLine(pt2, ptE, LS_FINITE)); } } else if (posS == PR_EDGE && posE == PR_OUTSIDE) { if (ptS == pt1) { show.push_back(XLine(pt2, ptE, LS_FINITE)); } else { show.push_back(XLine(pt1, ptE, LS_FINITE)); } } else if (posS == PR_OUTSIDE && posE == PR_EDGE) { if (ptE == pt1) { show.push_back(XLine(pt2, ptS, LS_FINITE)); } else { show.push_back(XLine(pt1, ptS, LS_FINITE)); } } return true; } if (nInter == 1) { if (posS == PR_OUTSIDE) { show.push_back(XLine(ptS, pt1, LS_FINITE)); hide.push_back(XLine(pt1, ptE, LS_FINITE)); } else { show.push_back(XLine(pt1, ptE, LS_FINITE)); hide.push_back(XLine(ptS, pt1, LS_FINITE)); } return true; } if (nInter == 0) { show.push_back(line); } return true; } // 返回 true 则完全在曲线内 bool JudgeRelationForLineAndPolyLine(const XLine &line, const XPoly2D &poly, std::vector > &show, std::vector > &hide, const int pos) { XPoint ptS = line.GetStartPoint(), ptE = line.GetEndPoint(); int posS = ptS & poly, posE = ptE & poly; // 直线在闭合曲线内(两点都在内,或一个在内,一个在边上,或都在边上) if ((posS == posE && posS == PR_INSIDE) || (posS == PR_EDGE && posE == PR_INSIDE) || (posS == PR_INSIDE && posE == PR_EDGE) || (posS == posE && posS == PR_EDGE)) { hide.push_back(std::make_pair(pos, line)); return false; } XPoint pt1, pt2; int nInter = Intersection(line, poly, pt1, pt2); // 直线在闭合曲线外(两点都在外(且与曲线无交点).或一个在外,一个在边上) if ((posS == posE && posS == PR_OUTSIDE && nInter < 2) || (posS == PR_EDGE && posE == PR_OUTSIDE && nInter == 1 && (pt1 == ptS || pt1 == ptE)) || (posS == PR_OUTSIDE && posE == PR_EDGE && nInter == 1 && (pt1 == ptS || pt1 == ptE))) { show.push_back(std::make_pair(pos, line)); return true; } if (nInter == 2) { hide.push_back(std::make_pair(pos, XLine(pt1, pt2, LS_FINITE))); if (posS == PR_OUTSIDE && posE == PR_OUTSIDE) { if (ptS.Distance(pt1) > ptS.Distance(pt2)) { show.push_back(std::make_pair(pos, XLine(ptS, pt2, LS_FINITE))); show.push_back(std::make_pair(pos, XLine(pt1, ptE, LS_FINITE))); } else { show.push_back(std::make_pair(pos, XLine(ptS, pt1, LS_FINITE))); show.push_back(std::make_pair(pos, XLine(pt2, ptE, LS_FINITE))); } } else if (posS == PR_EDGE && posE == PR_OUTSIDE) { if (ptS == pt1) { show.push_back(std::make_pair(pos, XLine(pt2, ptE, LS_FINITE))); } else { show.push_back(std::make_pair(pos, XLine(pt1, ptE, LS_FINITE))); } } else if (posS == PR_OUTSIDE && posE == PR_EDGE) { if (ptE == pt1) { show.push_back(std::make_pair(pos, XLine(pt2, ptS, LS_FINITE))); } else { show.push_back(std::make_pair(pos, XLine(pt1, ptS, LS_FINITE))); } } return true; } if (nInter == 1) { if (posS == PR_OUTSIDE) { show.push_back(std::make_pair(pos, XLine(ptS, pt1, LS_FINITE))); hide.push_back(std::make_pair(pos, XLine(pt1, ptE, LS_FINITE))); } else { show.push_back(std::make_pair(pos, XLine(pt1, ptE, LS_FINITE))); hide.push_back(std::make_pair(pos, XLine(ptS, pt1, LS_FINITE))); } return true; } if (nInter == 0) { show.push_back(std::make_pair(pos, line)); } return true; } } bool XCoverVisibleRelationCal::CoverVisibleCal( const ObjSectionRecord &top, ObjSectionRecord &low ) { if (EQUAL(top.GetElevation(), low.GetElevation())) return false; std::vector > new_show_lines(0), new_hide_lines(0); std::vector > &old_show_lines = low.GetSectionLines(); std::vector > &old_hide_lines = low.GetHideSectionLines(); for (size_t i = 0; i < old_show_lines.size(); ++i) { XLine line = old_show_lines[i].second; int nPart = old_show_lines[i].first; JudgeRelationForLineAndPolyLine(line, top.GetOriginalPoly(), new_show_lines, new_hide_lines, i); } old_hide_lines.insert(old_hide_lines.end(), new_hide_lines.begin(), new_hide_lines.end()); old_show_lines.swap(new_show_lines); if (old_show_lines.empty()) return true; return false; } void XCoverVisibleRelationCal::CoverMultipleRecordCal(std::vector & arObj) { std::sort(arObj.begin(), arObj.end(), std::greater()); // 排序,由大至小 size_t nCount = arObj.size(); ObjSectionRecord record; for (size_t i = 0; i < nCount; ++i) { ObjSectionRecord &record = arObj[i]; // 第一个曲线由于处于最上层,故不做处理 if (!i) continue; // 余下的曲线,要与排在它前面的每一个曲线进行遮挡运算. for (int j = i-1; j >= 0; --j) { // 如果record曲线已经被序号J曲线完全遮挡,则直接离开 if (CoverVisibleCal(arObj[j], record)) break; } } return; } // 使用此函数前最好对 arObj 进行排序 void XCoverVisibleRelationCal::PorcessCoverForFill( std::vector & arObj, std::vector &arFills ) { //std::sort(arObj.begin(), arObj.end(), std::greater()); // 排序,由大至小 for (size_t k = 0; k < arFills.size(); ++k) { for (int i = 0; i < arFills[k].length(); ++i) { XSectionFill *pFill = (XSectionFill*)arFills[k][i]; // 处理图块时,只判断其是否被遮挡 if (pFill->IsBlockRef()) { if (IsCoverBlockRef(arObj, *pFill, arFills)) // 被 投影结果 遮挡 直接判断下一个 { pFill->SetBlockCover(true); continue; } } else // 处理添充线时,不必考虑添充线之间的遮挡.因为线与线之间是没有遮挡关系的 { std::vector &segs = pFill->GetSegments(); std::vector &hidesegs = pFill->GetHideSegments(); std::vector::iterator pos = arObj.begin(); for ( ;pos != arObj.end(); ++pos) { if (pos->GetEntityType() == ObjSectionRecord::eAEC_ELEVTION) continue; std::vector showLines(0), hideLines(0); bool bContinu = false; bool bBreak = false; int nBreak = FALSE; for (size_t j = 0; j < segs.size(); ++j) { if (pos->GetElevation() <= pFill->GetElevation()) { bContinu = true; break; } XLine &line = segs[j]; nBreak += JudgeRelationForLineAndPolyLine(line, pos->GetOriginalPoly(), showLines, hideLines) ? 1 : 0; // if (!nBreak) // { // bBreak = true; // break; // } } if (bContinu) continue; if (bBreak) break; segs.swap(showLines); hidesegs.swap(hideLines); } } } } }