fix: HLR 退化圆弧按来源实体直径判断,并支持爬梯

在删除圆心角为 PI 的退化圆弧时,增加直径比较:
- 弯头(eElbow / eReduceElbow):带法兰(连接类型 3/5)取法兰外径 m_dInterfaceD,
  否则取画法直径 m_dD;
- 爬梯(AecDbClimbStair):取踏管直径 ClimbStair::dd。
仅当圆弧直径大于来源实体直径时才删除。

getElbowDiameter 改为 getSourceDiameter,removeFittingDegenerateArcs
改为 removeDegenerateArcs(已不止管件)。
This commit is contained in:
gjm committed 2026-10-16 23:20:57 +08:00
1 parent c0c04952dc
commit bbb899c0a0
1 file changed
+61 -17
+61 -17
View File
@@ -7,6 +7,7 @@
#include "HlrCutOption.h"
#include "aecdbewpipebase.h"
#include "AecDbEwFitting.h"
#include "AecDbClimbStair.h"
#include "compare_double.h"
#include "simpleproperty.h"
#include "hlrcommands.h"
@@ -535,9 +536,14 @@ namespace
//#endif
}
// 判断指定 id 的实体是否为 AecDbEwFitting。
bool isFittingId(const AcDbObjectId &id)
// 取得指定 id 对应实体用于与 HLR 结果圆弧比较的"直径"。目前处理两类来源:
// 弯头(eElbow / eReduceElbow):带法兰(连接类型 3 法兰管 / 5 法兰管线)时取法兰外径,
// 否则取弯头画法直径;
// 爬梯(AecDbClimbStair):取踏管直径。
// 其他实体返回 false(不处理)。
bool getSourceDiameter(const AcDbObjectId &id, double &dDiameter)
{
dDiameter = 0.0;
if (id == AcDbObjectId::kNull)
return false;
@@ -545,8 +551,37 @@ namespace
if (ent.openStatus() != Acad::eOk)
return false;
AcDbEntity *pEnt = ent;
return AecDbEwFitting::cast(pEnt) != NULL;
AcDbEntity *pEnt(ent);
// 爬梯:踏管直径
AecDbClimbStair *pStair(AecDbClimbStair::cast(pEnt));
if (pStair != NULL)
{
ClimbStair data;
memset(&data, 0, sizeof(ClimbStair));
pStair->GetClimbStairData(data);
dDiameter = data.dd;
return true;
}
// 弯头
AecDbEwFitting *pFit(AecDbEwFitting::cast(pEnt));
if (pFit == NULL)
return false;
const EFittingType eType(pFit->GetFittingType());
if (eType != eElbow && eType != eReduceElbow)
return false;
WPipe::PipeParam *pParam(pFit->GetPipeParam());
if (pParam == NULL)
return false;
const bool bFlange(pParam->m_nConnectType == 3 || pParam->m_nConnectType == 5);
dDiameter = bFlange ? pParam->m_dInterfaceD : pParam->m_dD;
delete pParam;
return true;
}
// result2 的键是"产生该批结果的实体指针",这类实体没有 id(是补充实体)。
@@ -569,32 +604,40 @@ namespace
}
// 判断 HLR 结果实体是否为需要删除的"退化圆弧":
// 实体是 AcDbArc,且圆心角为 PI(HLR 计算圆心角溢出后的特征)。
bool isDegenerateArcEntity(AcDbEntity *pEnt)
// 实体是 AcDbArc、圆心角为 PI(HLR 计算圆心角溢出后的特征),
// 且其直径大于来源实体的直径(超出实体本身范围,属错误结果)。
bool isDegenerateSourceArc(AcDbEntity *pEnt, const double &dSourceDiameter)
{
AcDbArc *pArc(AcDbArc::cast(pEnt));
if (pArc == NULL)
return false;
return COMPARE_DOUBLE::equal(pArc->totalAngle(), PI, 1e-9);
if (!COMPARE_DOUBLE::equal(pArc->totalAngle(), PI, 1e-9))
return false;
if (dSourceDiameter <= 1.e-6) // 取不到来源直径,无法比较,不删除
return false;
return COMPARE_DOUBLE::up_zero(pArc->radius() * 2.0 - dSourceDiameter, 1e-6);
}
// 删除 result1 / result2 中由 AecDbEwFitting 经 HLR 计算产生的、圆心角为 PI 的圆弧。
// result1 的键是数据库实体 id,直接判断该 id 是否为 AecDbEwFitting;
// result2 的键是无 id 的补充实体指针,需经 mpAdditional 反查归属的数据库实体 id 再判断。
void removeFittingDegenerateArcs(IDMapEntities &result1
// 删除 result1 / result2 中由弯头或爬梯经 HLR 计算产生的退化圆弧。
// result1 的键是数据库实体 id,直接取该 id 对应实体的直径;
// result2 的键是无 id 的补充实体指针,需经 mpAdditional 反查归属的数据库实体 id 再取直径。
void removeDegenerateArcs(IDMapEntities &result1
, EntMapEntities &result2
, const IDMapEntities &mpAdditional)
{
IDMapEntities::iterator it(result1.begin());
for (; it != result1.end(); ++it)
{
if (!isFittingId(it->first))
double dDiameter(0.0);
if (!getSourceDiameter(it->first, dDiameter))
continue;
for (int i(it->second.length() - 1); i >= 0; --i)
{
if (isDegenerateArcEntity(it->second[i]))
if (isDegenerateSourceArc(it->second[i], dDiameter))
{
delete it->second[i];
it->second.removeAt(i);
@@ -605,12 +648,13 @@ namespace
EntMapEntities::iterator it2(result2.begin());
for (; it2 != result2.end(); ++it2)
{
if (!isFittingId(fittingIdOfResultKey(it2->first, mpAdditional)))
double dDiameter(0.0);
if (!getSourceDiameter(fittingIdOfResultKey(it2->first, mpAdditional), dDiameter))
continue;
for (int i(it2->second.length() - 1); i >= 0; --i)
{
if (isDegenerateArcEntity(it2->second[i]))
if (isDegenerateSourceArc(it2->second[i], dDiameter))
{
delete it2->second[i];
it2->second.removeAt(i);
@@ -2051,8 +2095,8 @@ void AecDbXCamera::hlrCalc(AcDbObjectIdArray &arIds
HlrCalc(arIds, arAdditional_all, pVp.get(), control, result1, result2);
// 删除由 AecDbEwFitting 经 HLR 计算产生的"退化"圆弧(圆心角溢出为 PI)。
removeFittingDegenerateArcs(result1, result2, mpAdditional);
// 删除由弯头或爬梯经 HLR 计算产生的退化圆弧(圆心角溢出为 PI)。
removeDegenerateArcs(result1, result2, mpAdditional);
if (result1.empty() && result2.empty())
{