Merge pull request 'fix: HLR 结果中删除 AecDbEwFitting 产生的退化圆弧' (#11) from home-lenovo-legion-r9000/fix/aecdbcamera-fitting-degenerate-arc into main
Reviewed-on: https://git.ethereal-realm.top/gjm/envi-code/pulls/11
This commit was merged in pull request #11.
This commit is contained in:
commit
775b3c181c
1 file changed
+78
-40
@@ -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())
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user