重构底层

重构AecDbEntityBase,AecDbCurveBase
This commit is contained in:
gjm committed 2026-10-19 09:19:05 +08:00
1 parent 806726c11b
commit c84bc78869
7 files changed
+3578 -5819

No files matched your search

+342
View File
@@ -0,0 +1,342 @@
#pragma once
// ============================================================================
// AecDbEntityCommon.h
//
// 自定义实体的公共基类。
//
// AecDbEntityBase : public AcDbEntity
// AecDbCurveBase : public AcDbCurve
//
// 两者是两条平行的根(AcDb 类不能虚继承),历史上是两份逐行复制的实现。
// 本类不继承任何 AcDb / ARX 类,只承载两条根中 AcDbEntity 虚函数那一层,
// 以及它们必须的依赖(显示缓存、显示模式、写使能、静态工具)。
//
// 约定:
// 1. 需要 AcDb 基类的实现时,直接 GetMe()->AcDbEntity::xxx(...) 限定调用,
// 不为「AcDbEntity:: 还是 AcDbCurve::」另立钩子。
// AcDbCurve 没有重写这些接口(dwgInFields / subList / saveAs / setTransparency /
// setColorIndex / subWblockClone … 都在 AcDbEntity),两者是同一个实现。
// 2. 两族行为有差异的函数,本类给默认实现并声明为 virtual,
// 由有差异的那一族 override。不用 bool 开关参数,也不合并行为。
// 3. 需要回到 AcDb 一侧操作时走 GetMe()。
// ============================================================================
#include "dbmain.h"
#include "AcGiDraw.h"
#include "AecSubDef.h"
#include "shJson.h"
#include "EarThwormDef.h"
#pragma warning(disable: 4275 4251)
// 与 AecDbEntityBase.h 相同的导出规则:AecRxBase 内部导出,其它模块导入。
// 用独立宏名,避免与 AECDLLIMPEXP 的定义顺序互相影响。
#ifdef AECRXBASE_EXPORT
#define AECCOMMON_DLLIMPEXP __declspec(dllexport)
#else
#define AECCOMMON_DLLIMPEXP __declspec(dllimport)
#endif
class AecDbObjXDataMap;
class AcGiViewDraw;
class AcGiExplodeDraw;
namespace SimpleProperty { struct PropertySetByIndex; struct PropertySetByName; }
#ifndef _ttof
#define _ttof(pszVal) _tcstod((pszVal), NULL)
#endif
class AECCOMMON_DLLIMPEXP AecDbEntityCommon
{
public:
AecDbEntityCommon(void);
virtual ~AecDbEntityCommon(void);
protected:
// 世界绘制:原 AecDbEntityBase::subWorldDraw / AecDbCurveBase::subWorldDraw
// 逐行一致。subWorldDraw 是 AcGiDrawable 的虚函数,本类不在 AcDb 继承链上,
// 只能由两个根各自留一行转发。
virtual Adesk::Boolean base_WorldDraw(AcGiWorldDraw* pWd);
// 视口绘制:原两个根的 subViewportDraw 逐行一致,同样只能由两个根转发。
virtual void base_ViewportDraw(AcGiViewportDraw* pMode);
// 视口绘制标志 / 绘制属性:原两个根逐行一致。
// 这两个接口在 AcDb 一侧是 protected,本类取不到,由两个根先调基类、
// 把基类结果作为 nBaseFlags 传进来,这里只负责叠加自己的标志位。
virtual Adesk::UInt32 base_ViewportDrawLogicalFlags(Adesk::UInt32 nBaseFlags);
virtual Adesk::UInt32 base_SetAttributes(Adesk::UInt32 nBaseFlags);
// 炸开:原两个根的 subExplode 逐行一致。
virtual Acad::ErrorStatus base_Explode(AcDbVoidPtrArray& entitySet) const;
// 保存代理实体图元:原两个根的 saveAs 逐行一致。
// 代理分支要回到具体实体自己的 subWorldDraw(子类可能重写),走 CallWorldDraw。
virtual void base_SaveAs(AcGiWorldDraw* pWd, AcDb::SaveType saveType);
// 几何范围:原两个根的 subGetGeomExtents 逐行一致。
virtual Acad::ErrorStatus base_GetGeomExtents(AcDbExtents& extents) const;
// 对象捕捉点(第一个重载):原两个根逐行一致。
virtual Acad::ErrorStatus base_GetOsnapPoints(AcDb::OsnapMode osnapMode,
INT_PTR gsSelectionMark,
const AcGePoint3d& ptPick,
const AcGePoint3d& lastPoint,
const AcGeMatrix3d& viewXform,
AcGePoint3dArray& snapPoints,
AcDbIntArray& geomIds) const;
virtual Acad::ErrorStatus base_DeepClone( AcDbObject* pOwnerObject,
AcDbObject*& pClonedObject,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary = Adesk::kTrue) const;
virtual Acad::ErrorStatus base_WblockClone( AcRxObject* pOwnerObject,
AcDbObject*& pClonedObject,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary = Adesk::kTrue) const;
// 桥:转调 AcDb 一侧原生的 subWblockClone(fast wblock 时用它交回基类)。
// subWblockClone 在 AcDbObject 里是 protected,本类不在继承链上,
// 只能由两个根各自转调,限定 AcDbEntity:: / AcDbCurve::。
virtual Acad::ErrorStatus CallAcDbWblockClone(AcRxObject* pOwnerObject,
AcDbObject*& pClonedObject,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary) const = 0;
// 桥:回到具体实体自己的 subWorldDraw(子类可能重写,saveAs 的代理分支要用)。
// subWorldDraw 在 AcGiDrawable 里是 protected,本类不在继承链上取不到。
virtual Adesk::Boolean CallWorldDraw(AcGiWorldDraw* pWd) = 0;
// ------------------------------------------------------------------
// 桥:由 AecDbEntityBase / AecDbCurveBase 实现
// ------------------------------------------------------------------
public:
// 回到 AcDb 一侧。两个根的 AcDb 根都是第一个基类,实现为 return this;
virtual AcDbEntity* GetMe() = 0;
virtual const AcDbEntity* GetMe() const = 0;
virtual bool IsThisMe(const AcDbEntity *pEnt) const = 0;
// 专业数据容器(两个根原本就是纯虚接口)
virtual AecDbObjXDataMap* GetSpecialtyData(AcDb::OpenMode bMode = AcDb::kForWrite) = 0;
virtual const AecDbObjXDataMap* GetSpecialtyData() const = 0;
//获取当前显示模式
int GetDrawDimCur() const;
// 得到实体唯一得名字,revit 通过这个字符串来判断是否有同样得实体
// 如果有,则在revit中可以生成一个族来替代这些同样得实体,以加快速度
virtual CString getUniqueName() const;
virtual void NewGUID() {}
virtual double GetArea() const {return .0;}
virtual void PreprocessForHlr( const AcGePoint3d &ptPlnO
, const AcGeVector3d &vtPlnN
, AcArray<AcDbEntity*> &ar) const;
/*
此函数只修改 ar内的实体的 图层、线型、颜色, 但线宽不处理
如有其他要求,重载
ar 是 hlr 通过调用实体的Draw3d函数得到的结果
preAr 中的 first(AcDbEntity*) 来自于 “PreprocessForHlr” 函数得到的实体指针
preAr 中的 second 来自于 first 经过 hlr 计算之后的结果
基类不处理 preAr
*/
virtual void ProcessHlrResult(const AcArray<AcDbEntity*> &ar
, const std::map<AcDbEntity*, AcArray<AcDbEntity*>> &preAr
, AcArray<AcDbEntity*> &output ) const;
virtual bool GetBimInfoTip(CString& sInfoTip) const;
// 为方便用户查询实体的属性,可以重载此函数,目前,此函数使用在“实体快速选择”功能上
virtual bool GetProperties(SimpleProperty::PropertySetByIndex &porpertys) const;
virtual bool SetProperties(SimpleProperty::PropertySetByName &porpertys);
// 导出json
virtual SHJson::WValue& ToJson(bool bExprotGeo = true) const;
// 通过json创建
virtual bool ByJson(const SHJson::WValue &v);
//获取体积
virtual double GetVolume(bool bIsBody = false) const;
virtual void SetActive(bool bActive) {};
virtual bool IsActive() const { return false; }
protected:
// 子类真正实现的绘制入口(两个根的默认实现都是 return eOk)
virtual Acad::ErrorStatus Draw2d(AcGiDraw& dc) const;
virtual Acad::ErrorStatus Draw3d(AcGiDraw& dc) const;
virtual void AssertWriteEnabled(Adesk::Boolean autoUndo = true, Adesk::Boolean recordModified = true);
protected:
static int GetDrawMode();
static void SetDrawMode(int nMode);
static void BackupColorIndex(AcDbEntity* pEnt);
static int SetBackupColorIndex(AcDbEntity* pEnt);
//获取炸碎2D/3d模式
int GetExplodeMode() const;
//获取显示维度 0--NONE; 1--2D; 2--3D; 3--2D&3D
int GetDrawDimOnType(int nDrawMode, int nDrawType) const;
//2023-6-26 增加单击夹点发送命令DBL_DXF
virtual bool GetPositionGrip(int nIndex, AecGripData *&pGrip) const { return NULL; }
bool SubAddHitEditGrip(AcDbGripDataPtrArray &grips) const;
bool HitOnGripEdit(const AcDbVoidPtrArray &gripAppData);
public:
// 2d 缓存操作
virtual bool Draw2DBuffers(AcGiDraw &dc) const;
const AcDbVoidPtrArray& Get2DBuffer()const;
bool Has2DBuffer()const;
void Add2DBuffer(AcDbEntity *pEnt)const;
void Add2DBuffer(const AcDbVoidPtrArray &arr)const;
bool IsIn2DBuffer(AcDbEntity* pEnt) const;
void Clean2DBuffer()const;
void Clean2DBufferNoDel()const;
// 3d 缓存操作
bool Draw3DBuffers(AcGiDraw &dc) const;
const AcDbVoidPtrArray &Get3DBuffer()const;
bool Has3DBuffer()const;
void Add3DBuffer(AcDbEntity *pEnt)const;
void Add3DBuffer(const AcDbVoidPtrArray &arr)const;
bool IsIn3DBuffer(AcDbEntity *pEnt) const;
void Clean3DBuffer()const;
void Clean3DBufferNoDel()const;
Acad::ErrorStatus ReCreateDraw2d();
Acad::ErrorStatus ReCreateDraw3d();
//获取二维视图显示的图形
virtual int GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray &arEntPtrs) const;
//获取三维显示图形
virtual int GetDraw3dables(AcDbVoidPtrArray &arEntPtrs, bool bWriteBimInfo = false) const;
//用户级别的数据调用消息
virtual bool SendUserData(struct resbuf *pRb) { return false; }
virtual int GetSectionDraw(const AcGePoint3d &ptFr
, const AcGePoint3d &ptTo
, const AcGeVector3d &vtViewDir
, const AcGeVector3d &vtTo
, AcDbVoidPtrArray &arRegionPtrs) const { return 0; }
virtual AcDb3dSolid *GetBlackHole() const { return NULL; }
//剖切提取
bool GetSectionHatchPattern(CString& sPattern) const;
void BoolSubtractHide() const;
Acad::ErrorStatus subGet3dGeomExtents(AcDbExtents &extents) const;
void Add3DBoolSubtract(AcDb3dSolid* pSolidBlackHole);
void Remove3DBoolSubtract();
void AddBlackHole(AcDbObjectId& idHole);
void RemoveBlackHole(AcDbObjectId& idHole);
void DrawBlackHole(AcDbEntity* pSolidEnt) const;
void UpdateDrableSpecData(LPCTSTR pszApp,LPCTSTR pszKey,CString& sVal);
//按分隔符拆字符串(CoreLibrary / PipelineCmd 等多处按 AecDbEntityBase:: 限定调用)
static void SplitStrintToArray(LPCTSTR pszDescr, CStringArray & arInfo, TCHAR tcSpace);
protected:
// 绘制函数被调用的方式(WorldDraw / ViewportDraw / Explode)
// mutable:subExplode 是 const 函数,原实现靠 const_cast 写入
mutable ExplodeOrDrawType m_eExplodeOrDrawType;
// 最近一次实际绘制的是 2D / 3D(-1 表示尚未绘制)
short m_nDrawDimCur;
// 2D / 3D 显示缓存
mutable AcDbVoidPtrArray m_ar2DDrableBufPtrs_;//临时缓存 俯视图
mutable AcDbVoidPtrArray m_ar3DDrableBufPtrs_;//临时缓存
private:
mutable SHJson::WValue m_json;
public:
template<typename T>
BOOL GetAt(LPCTSTR pszKey, T &va) const
{
const AecDbObjXDataMap *pMap(GetSpecialtyData());
if (!pMap) return FALSE;
return pMap->GetAt(pszKey, va);
}
template<typename T1, typename T2>
BOOL GetAt(LPCTSTR pszKey, T1 va1, T2 va2) const
{
const AecDbObjXDataMap *pMap(GetSpecialtyData());
if (!pMap) return FALSE;
return pMap->GetAt(pszKey, va1, va2);
}
template <int N>
BOOL GetAt(LPCTSTR pszKey, TCHAR(&va)[N]) const
{
const AecDbObjXDataMap *pMap(GetSpecialtyData());
if (!pMap) return FALSE;
CString s;
if (pMap->GetAt(pszKey, s) == FALSE) return FALSE;
_tcsncpy_s(va, N, s, N - 1);
return TRUE;
}
template <int N>
BOOL GetAt(LPCTSTR pszKey, LPTSTR va) const
{
const AecDbObjXDataMap *pMap(GetSpecialtyData());
if (!pMap) return FALSE;
CString s;
if (pMap->GetAt(pszKey, s) == FALSE) return FALSE;
_tcsncpy_s(va, N, s, N - 1);
return TRUE;
}
template<typename T>
BOOL SetAt(LPCTSTR pszKey, T va)
{
AecDbObjXDataMap *pMap(GetSpecialtyData(AcDb::kForWrite));
if (!pMap) return FALSE;
return pMap->SetAt(pszKey, va);
}
template<typename T1, typename T2>
BOOL SetAt(LPCTSTR pszKey, T1 va1, T2 va2)
{
AecDbObjXDataMap *pMap(GetSpecialtyData(AcDb::kForWrite));
if (!pMap) return FALSE;
return pMap->SetAt(pszKey, va1, va2);
}
template <class K> static BOOL CopyObject(const K &src, K &dest)
{
AcDbDeepCloneFiler filer;
BOOL bRet = FALSE;
if (src.dwgOutFields(&filer) == Acad::eOk)
{
filer.seek(0L, 0);
bRet = (dest.dwgInFields(&filer) == Acad::eOk);
}
return bRet;
}
};