430 lines
12 KiB
C++
430 lines
12 KiB
C++
#include "StdAfx.h"
|
|
#include <functional>
|
|
#include "XCoverVisibleRelationCal.h"
|
|
#include "XCurveInline.h"
|
|
#include <algorithm>
|
|
#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<ObjSectionRecord> &records, XSectionFill &fill,
|
|
const std::vector<AcDbVoidPtrArray> &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<XLine> &show, std::vector<XLine> &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<std::pair<int, XLine> > &show, std::vector<std::pair<int, XLine> > &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<std::pair<int, XLine> > new_show_lines(0), new_hide_lines(0);
|
|
|
|
std::vector<std::pair<int ,XLine> > &old_show_lines = low.GetSectionLines();
|
|
std::vector<std::pair<int ,XLine> > &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<ObjSectionRecord> & arObj)
|
|
{
|
|
std::sort(arObj.begin(), arObj.end(), std::greater<ObjSectionRecord>()); // 排序,由大至小
|
|
|
|
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<ObjSectionRecord> & arObj, std::vector<AcDbVoidPtrArray> &arFills )
|
|
{
|
|
//std::sort(arObj.begin(), arObj.end(), std::greater<ObjSectionRecord>()); // 排序,由大至小
|
|
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<XLine> &segs = pFill->GetSegments();
|
|
std::vector<XLine> &hidesegs = pFill->GetHideSegments();
|
|
|
|
std::vector<ObjSectionRecord>::iterator pos = arObj.begin();
|
|
for ( ;pos != arObj.end(); ++pos)
|
|
{
|
|
if (pos->GetEntityType() == ObjSectionRecord::eAEC_ELEVTION)
|
|
continue;
|
|
|
|
std::vector<XLine> 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|