#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 &ar) const; /* 此函数只修改 ar内的实体的 图层、线型、颜色, 但线宽不处理 如有其他要求,重载 ar 是 hlr 通过调用实体的Draw3d函数得到的结果 preAr 中的 first(AcDbEntity*) 来自于 “PreprocessForHlr” 函数得到的实体指针 preAr 中的 second 来自于 first 经过 hlr 计算之后的结果 基类不处理 preAr */ virtual void ProcessHlrResult(const AcArray &ar , const std::map> &preAr , AcArray &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 BOOL GetAt(LPCTSTR pszKey, T &va) const { const AecDbObjXDataMap *pMap(GetSpecialtyData()); if (!pMap) return FALSE; return pMap->GetAt(pszKey, va); } template BOOL GetAt(LPCTSTR pszKey, T1 va1, T2 va2) const { const AecDbObjXDataMap *pMap(GetSpecialtyData()); if (!pMap) return FALSE; return pMap->GetAt(pszKey, va1, va2); } template 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 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 BOOL SetAt(LPCTSTR pszKey, T va) { AecDbObjXDataMap *pMap(GetSpecialtyData(AcDb::kForWrite)); if (!pMap) return FALSE; return pMap->SetAt(pszKey, va); } template BOOL SetAt(LPCTSTR pszKey, T1 va1, T2 va2) { AecDbObjXDataMap *pMap(GetSpecialtyData(AcDb::kForWrite)); if (!pMap) return FALSE; return pMap->SetAt(pszKey, va1, va2); } template 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; } };