Files
envi-code/SourceCode/Code2026/tg_shs/shs_geLib/TCoverVisibleRelationCal.cpp
T
2026-09-28 15:28:50 +08:00

430 lines
12 KiB
C++

#include "StdAfx.h"
#include "TCoverVisibleRelationCal.h"
#include "TGGeCurveInline.h"
#include <algorithm>
#include "SectionUtility.h"
#include "TchGlobalFunc.h"
#include <functional>
#define SET_LINE_PT(line, pt1, pt2)\
line.SetStartPoint(pt1);\
line.SetEndPoint(pt2)
namespace
{
int GetPointPosInPoly2d(const TGGePoly2D &poly, const TADSGePoint3d &pt)
{
for (int i = 0; i < poly.Length(); ++i)
{
if (pt == poly[i])
return i;
}
return -1;
}
bool IsIntersection(const TGGePoly2D &Low, const TGGePoly2D &Top)
{
for (int i = 0; i < SectionUtility::GetCountOfSegmentForPoly(Low)/*Low.TotalSegments()*/; ++i)
{
TGGeCurveSegment segLow = SectionUtility::GetSegmentOfPoly(Low, i);
/*Low.Nth(i, segLow);*/
for (int j = 0; j < SectionUtility::GetCountOfSegmentForPoly(Top)/*Top.TotalSegments()*/; ++j)
{
TGGeCurveSegment segTop = SectionUtility::GetSegmentOfPoly(Top, j);
// Top.Nth(j, segTop);
TADSGePoint3d pt;
if (segLow.Intersection(segTop, pt, pt))
return true;
}
}
return false;
}
TCoverVisibleRelationCal::SectionRelative CanCover(const TGGePoly2D &Low, const TGGePoly2D &Top)
{
if (IsIntersection(Low, Top))
return TCoverVisibleRelationCal::kIntersection;
if (SectionUtility::GetCountOfSegmentForPoly(Top)/*Top.TotalSegments()*/ == 1) // 如果top面只有一根曲线,则不用计算遮挡关系
return TCoverVisibleRelationCal::kLowContainTop;
if (PR_OUTSIDE != (Top[0] & Low)) // 如top面的顶点有一点在low 面内,则low面包含top面
return TCoverVisibleRelationCal::kLowContainTop;
else if (PR_OUTSIDE != (Low[0] & Top)) // 如low面的顶点有一点在top 面内,则top面包含low面
return TCoverVisibleRelationCal::kTopContainLow;
else // 两个面的顶点都在对方的外面,则互不包含
return TCoverVisibleRelationCal::kNoneIntersection;
}
bool IsCoverBlockRef(const std::vector<TObjSectionRecord> &records, TSectionFill &fill,
const std::vector<AcDbVoidPtrArray> &fills)
{
BlockRefInfo block;
fill.GetBlockRefInfo(block);
TGGePoly2D poly = block.ToPoly2D();
// 判断与 投影结果 的遮挡关系
for (size_t i = 0; i < records.size(); ++i)
{
// 判断与 投影面的距离 的大小,如record曲线大于fill曲线的,则说明 record的曲线在 fill曲线后面
// 则不进行遮挡判断
if (records[i].GetElevation() <= block.m_dHeight)
continue;
TCoverVisibleRelationCal::SectionRelative rela = CanCover(poly, records[i].GetOriginalPoly());
// fill 曲线 包含 record 曲线 或 两曲线完全不包含
if (rela == TCoverVisibleRelationCal::kLowContainTop || rela == TCoverVisibleRelationCal::kNoneIntersection)
continue;
else
return true;
}
// 判断与 其它 添充对象的遮挡关系
for (i = 0; i < fills.size(); ++i)
{
for (int k = 0; k < fills[i].length(); ++k)
{
TSectionFill *pFill = (TSectionFill*)fills[i][k];
BlockRefInfo _block;
pFill->GetBlockRefInfo(_block);
if (_block.m_dHeight <= block.m_dHeight)
continue;
TGGePoly2D _poly = _block.ToPoly2D();
TCoverVisibleRelationCal::SectionRelative rela = CanCover(poly, _poly);
// fill 曲线 包含 record 曲线 或 两曲线完全不包含
if (rela == TCoverVisibleRelationCal::kLowContainTop || rela == TCoverVisibleRelationCal::kNoneIntersection)
continue;
else
return true;
}
}
return false;
}
// 返回1 两个交点,返回2 一个交点
int Intersection(const TGGeLine &line, const TGGePoly2D &poly,
TADSGePoint3d &pt1, TADSGePoint3d &pt2)
{
TGGePoly2D tmp;
for (int i = 0; i < SectionUtility::GetCountOfSegmentForPoly(poly)/*poly.TotalSegments()*/; ++i)
{
TADSGePoint3d pt;
TGGeCurveSegment 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 TGGeLine &line, const TGGePoly2D &poly,
std::vector<TGGeLine> &show, std::vector<TGGeLine> &hide)
{
TADSGePoint3d 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;
}
TADSGePoint3d 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(TGGeLine(pt1, pt2, LS_FINITE));
if (posS == PR_OUTSIDE && posE == PR_OUTSIDE)
{
if (ptS.Distance(pt1) > ptS.Distance(pt2))
{
show.push_back(TGGeLine(ptS, pt2, LS_FINITE));
show.push_back(TGGeLine(pt1, ptE, LS_FINITE));
}
else
{
show.push_back(TGGeLine(ptS, pt1, LS_FINITE));
show.push_back(TGGeLine(pt2, ptE, LS_FINITE));
}
}
else if (posS == PR_EDGE && posE == PR_OUTSIDE)
{
if (ptS == pt1)
{
show.push_back(TGGeLine(pt2, ptE, LS_FINITE));
}
else
{
show.push_back(TGGeLine(pt1, ptE, LS_FINITE));
}
}
else if (posS == PR_OUTSIDE && posE == PR_EDGE)
{
if (ptE == pt1)
{
show.push_back(TGGeLine(pt2, ptS, LS_FINITE));
}
else
{
show.push_back(TGGeLine(pt1, ptS, LS_FINITE));
}
}
return true;
}
if (nInter == 1)
{
if (posS == PR_OUTSIDE)
{
show.push_back(TGGeLine(ptS, pt1, LS_FINITE));
hide.push_back(TGGeLine(pt1, ptE, LS_FINITE));
}
else
{
show.push_back(TGGeLine(pt1, ptE, LS_FINITE));
hide.push_back(TGGeLine(ptS, pt1, LS_FINITE));
}
return true;
}
if (nInter == 0)
{
show.push_back(line);
}
return true;
}
// 返回 true 则完全在曲线内
bool JudgeRelationForLineAndPolyLine(const TGGeLine &line, const TGGePoly2D &poly,
std::vector<std::pair<int, TGGeLine> > &show, std::vector<std::pair<int, TGGeLine> > &hide, const int pos)
{
TADSGePoint3d 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;
}
TADSGePoint3d 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, TGGeLine(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, TGGeLine(ptS, pt2, LS_FINITE)));
show.push_back(std::make_pair(pos, TGGeLine(pt1, ptE, LS_FINITE)));
}
else
{
show.push_back(std::make_pair(pos, TGGeLine(ptS, pt1, LS_FINITE)));
show.push_back(std::make_pair(pos, TGGeLine(pt2, ptE, LS_FINITE)));
}
}
else if (posS == PR_EDGE && posE == PR_OUTSIDE)
{
if (ptS == pt1)
{
show.push_back(std::make_pair(pos, TGGeLine(pt2, ptE, LS_FINITE)));
}
else
{
show.push_back(std::make_pair(pos, TGGeLine(pt1, ptE, LS_FINITE)));
}
}
else if (posS == PR_OUTSIDE && posE == PR_EDGE)
{
if (ptE == pt1)
{
show.push_back(std::make_pair(pos, TGGeLine(pt2, ptS, LS_FINITE)));
}
else
{
show.push_back(std::make_pair(pos, TGGeLine(pt1, ptS, LS_FINITE)));
}
}
return true;
}
if (nInter == 1)
{
if (posS == PR_OUTSIDE)
{
show.push_back(std::make_pair(pos, TGGeLine(ptS, pt1, LS_FINITE)));
hide.push_back(std::make_pair(pos, TGGeLine(pt1, ptE, LS_FINITE)));
}
else
{
show.push_back(std::make_pair(pos, TGGeLine(pt1, ptE, LS_FINITE)));
hide.push_back(std::make_pair(pos, TGGeLine(ptS, pt1, LS_FINITE)));
}
return true;
}
if (nInter == 0)
{
show.push_back(std::make_pair(pos, line));
}
return true;
}
}
bool TCoverVisibleRelationCal::CoverVisibleCal( const TObjSectionRecord &top, TObjSectionRecord &low )
{
if (EQUAL(top.GetElevation(), low.GetElevation()))
return false;
std::vector<std::pair<int, TGGeLine> > new_show_lines(0), new_hide_lines(0);
std::vector<std::pair<int ,TGGeLine> > &old_show_lines = low.GetSectionLines();
std::vector<std::pair<int ,TGGeLine> > &old_hide_lines = low.GetHideSectionLines();
for (size_t i = 0; i < old_show_lines.size(); ++i)
{
TGGeLine 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 TCoverVisibleRelationCal::CoverMultipleRecordCal(std::vector<TObjSectionRecord> & arObj)
{
std::sort(arObj.begin(), arObj.end(), std::greater<TObjSectionRecord>()); // 排序,由大至小
size_t nCount = arObj.size();
TObjSectionRecord record;
for (size_t i = 0; i < nCount; ++i)
{
TObjSectionRecord &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 TCoverVisibleRelationCal::PorcessCoverForFill( std::vector<TObjSectionRecord> & arObj, std::vector<AcDbVoidPtrArray> &arFills )
{
//std::sort(arObj.begin(), arObj.end(), std::greater<TObjSectionRecord>()); // 排序,由大至小
for (size_t k = 0; k < arFills.size(); ++k)
{
for (int i = 0; i < arFills[k].length(); ++i)
{
TSectionFill *pFill = (TSectionFill*)arFills[k][i];
// 处理图块时,只判断其是否被遮挡
if (pFill->IsBlockRef())
{
if (IsCoverBlockRef(arObj, *pFill, arFills)) // 被 投影结果 遮挡 直接判断下一个
{
pFill->SetBlockCover(true);
continue;
}
}
else // 处理添充线时,不必考虑添充线之间的遮挡.因为线与线之间是没有遮挡关系的
{
std::vector<TGGeLine> &segs = pFill->GetSegments();
std::vector<TGGeLine> &hidesegs = pFill->GetHideSegments();
std::vector<TObjSectionRecord>::iterator pos = arObj.begin();
for ( ;pos != arObj.end(); ++pos)
{
if (pos->GetEntityType() == TObjSectionRecord::eTCH_ELEVTION)
continue;
std::vector<TGGeLine> 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;
}
TGGeLine &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);
}
}
}
}
}