From c0c04952dc9bf3a47639685e7783539cf9a300ed Mon Sep 17 00:00:00 2001 From: LittleGuo Date: Fri, 16 Oct 2026 21:34:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20HLR=20=E7=BB=93=E6=9E=9C=E4=B8=AD?= =?UTF-8?q?=E5=88=A0=E9=99=A4=20AecDbEwFitting=20=E4=BA=A7=E7=94=9F?= =?UTF-8?q?=E7=9A=84=E9=80=80=E5=8C=96=E5=9C=86=E5=BC=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原 isDegenerateArc 以 弧长/半径 比值判断退化圆弧,且无法区分结果来源。 改为按来源实体类型判断: - result1 的键是数据库实体 id,直接判断该 id 是否为 AecDbEwFitting; - result2 的键是无 id 的补充实体指针,先经 mpAdditional (数据库实体id -> 其产生的补充实体) 反查归属的数据库实体 id,再判断。 删除规则:结果实体是 AcDbArc 且圆心角为 PI 时删除。 --- .../Code2026/CoreLibrary/AecDbCamera.cpp | 118 ++++++++++++------ 1 file changed, 78 insertions(+), 40 deletions(-) diff --git a/SourceCode/Code2026/CoreLibrary/AecDbCamera.cpp b/SourceCode/Code2026/CoreLibrary/AecDbCamera.cpp index aeb0ab9..84d012b 100644 --- a/SourceCode/Code2026/CoreLibrary/AecDbCamera.cpp +++ b/SourceCode/Code2026/CoreLibrary/AecDbCamera.cpp @@ -6,6 +6,7 @@ #include "CoreTools.h" #include "HlrCutOption.h" #include "aecdbewpipebase.h" +#include "AecDbEwFitting.h" #include "compare_double.h" #include "simpleproperty.h" #include "hlrcommands.h" @@ -534,24 +535,88 @@ namespace //#endif } - // 弧长/半径 的比值小于此值即视为"退化圆弧"(圆心角极小)。 - const double kMinArcLengthRadiusRatio = 1e-6; + // 判断指定 id 的实体是否为 AecDbEwFitting。 + bool isFittingId(const AcDbObjectId &id) + { + if (id == AcDbObjectId::kNull) + return false; - // 判断 HLR 结果实体是否为"退化圆弧":实体是 AcDbArc,且 弧长/半径 的比值极小。 - // 这类圆弧的圆心角极小,HLR 计算时圆心角会溢出,使结果由"很小一段"变成 - // "反向的大圆弧",需要从结果中删除。 - bool isDegenerateArc(AcDbEntity *pEnt) + AcDbEntityPointer ent(id, AcDb::kForRead); + if (ent.openStatus() != Acad::eOk) + return false; + + AcDbEntity *pEnt = ent; + return AecDbEwFitting::cast(pEnt) != NULL; + } + + // result2 的键是"产生该批结果的实体指针",这类实体没有 id(是补充实体)。 + // 补充实体由某个数据库实体产生,mpAdditional 记录了"数据库实体id -> 其产生的补充实体", + // 因此需反查该指针归属的数据库实体 id,再用该 id 判断类型。 + // 找不到归属(例如构筑物融合后不在数据库中的实体)时返回 kNull。 + AcDbObjectId fittingIdOfResultKey(AcDbEntity *pSrc, const IDMapEntities &mpAdditional) + { + if (pSrc == NULL) + return AcDbObjectId::kNull; + + IDMapEntities::const_iterator it(mpAdditional.begin()); + for (; it != mpAdditional.end(); ++it) + { + if (it->second.find(pSrc) != -1) // pSrc 是该 id 产生的补充实体 + return it->first; + } + + return AcDbObjectId::kNull; + } + + // 判断 HLR 结果实体是否为需要删除的"退化圆弧": + // 实体是 AcDbArc,且圆心角为 PI(HLR 计算圆心角溢出后的特征)。 + bool isDegenerateArcEntity(AcDbEntity *pEnt) { AcDbArc *pArc(AcDbArc::cast(pEnt)); if (pArc == NULL) return false; - double dRadius(pArc->radius()); - if (COMPARE_DOUBLE::equal_zero(dRadius, 1e-9)) - return true; // 半径≈0,本身即退化 + return COMPARE_DOUBLE::equal(pArc->totalAngle(), PI, 1e-9); + } - double dRatio(pArc->length() / dRadius); - return dRatio < kMinArcLengthRadiusRatio; + // 删除 result1 / result2 中由 AecDbEwFitting 经 HLR 计算产生的、圆心角为 PI 的圆弧。 + // result1 的键是数据库实体 id,直接判断该 id 是否为 AecDbEwFitting; + // result2 的键是无 id 的补充实体指针,需经 mpAdditional 反查归属的数据库实体 id 再判断。 + void removeFittingDegenerateArcs(IDMapEntities &result1 + , EntMapEntities &result2 + , const IDMapEntities &mpAdditional) + { + IDMapEntities::iterator it(result1.begin()); + for (; it != result1.end(); ++it) + { + if (!isFittingId(it->first)) + continue; + + for (int i(it->second.length() - 1); i >= 0; --i) + { + if (isDegenerateArcEntity(it->second[i])) + { + delete it->second[i]; + it->second.removeAt(i); + } + } + } + + EntMapEntities::iterator it2(result2.begin()); + for (; it2 != result2.end(); ++it2) + { + if (!isFittingId(fittingIdOfResultKey(it2->first, mpAdditional))) + continue; + + for (int i(it2->second.length() - 1); i >= 0; --i) + { + if (isDegenerateArcEntity(it2->second[i])) + { + delete it2->second[i]; + it2->second.removeAt(i); + } + } + } } bool zeroLength(AcDbCurve *pCrv, const double &tol) @@ -1986,35 +2051,8 @@ void AecDbXCamera::hlrCalc(AcDbObjectIdArray &arIds HlrCalc(arIds, arAdditional_all, pVp.get(), control, result1, result2); - // 删除 HLR 计算中"退化"的圆弧(弧长/半径 比值极小)。 - // 这类圆弧圆心角极小,计算时会溢出,由"很小一段"变成"反向的大圆弧"。 - { - IDMapEntities::iterator it(result1.begin()); - for (; it != result1.end(); ++it) - { - for (int i(it->second.length() - 1); i >= 0; --i) - { - if (isDegenerateArc(it->second[i])) - { - delete it->second[i]; - it->second.removeAt(i); - } - } - } - - EntMapEntities::iterator it2(result2.begin()); - for (; it2 != result2.end(); ++it2) - { - for (int i(it2->second.length() - 1); i >= 0; --i) - { - if (isDegenerateArc(it2->second[i])) - { - delete it2->second[i]; - it2->second.removeAt(i); - } - } - } - } + // 删除由 AecDbEwFitting 经 HLR 计算产生的"退化"圆弧(圆心角溢出为 PI)。 + removeFittingDegenerateArcs(result1, result2, mpAdditional); if (result1.empty() && result2.empty()) {