Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

428 lines
17 KiB
C++

// 用于处理门窗检查
#pragma once
#include "BayWindow.h"
namespace NDoorWinCheck
{
// 洞分类:
// 门, 门连窗,子母门, 组合门窗, 窗, 弧窗, 凸窗, 转角窗, 带形窗, 老虎窗, 洞口
enum EEntType{eM = 0, eMLC, eZMM, eZHMC, eC, eHC, eTC, eZJC, eDXC, eLHC, eDK, eDoorTypeNum};
enum EShowItem
{
eTypeProp = 0x1, // 类型
eWidProp = 0x2, // 长度
eHeiProp = 0x4, // 高度
eEle = 0x8, // 底高
eGeoTypeProp = 0x10, // 型式
eChutiaoProp = 0x20, // 出挑长
eTixingkuanProp = 0x40, // 梯形宽
eNewLabelProp = 0x80, // 新编号
eLabelProp = 0x100,// 编号
// 下边是类型的索引,可以实现两者的转化
eLabelIndex = 0, eNewLabelIndex , eTypeIndex, eWidIndex,
eHeiIndex, eEleIndex, eGeoTypeIndex, eChutiaoIndex, eTixingkuanIndex, eDoorWinParmNum
};
#define IsCADClosed() (curDoc() == NULL)
// ShowItemIndex ==> ShowItemProp
EShowItem GetShowItem(EShowItem eShowIndex);
// ShowItemProp ==>ShowItemIndex;
EShowItem ShowItem2Index(EShowItem eShowItem);
// 属性类型 ==> 字符串名称
CString ParamTypeToString(EShowItem type);
// 检测是否是文本具有的属性,文本只具有宽度,高度和新编号属性
BOOL IsTextShowItem(EShowItem eItem);
// 更新显示,不管ID对应的是普通实体,块参照实体,或者外部参照实体
void UpdateGraphicAny(const TDPtrList<AcDbObjectId> &ss);
// 锁定文档防止切换
void LockDocumentChange();
// 解除文档切换锁定。
void UnLockDocumentChange();
// 判断一个类型是否需要显示门窗样式
BOOL IsSlideType(EEntType eEntType);
#define IsCheckText() (CSetDlg::CheckText() ? true : false)
#define IsCheckDWG() (CSetDlg::CheckCurrDWG() ? true : false)
#define IsCheckProj() (CSetDlg::CheckCurrProj() ? true : false)
#define IsCheckBlock() (CSetDlg::CheckBlock() ? true : false)
struct CItem;
struct CWidItem;
typedef CArray<EShowItem, EShowItem> AryEShowItem;
typedef CArray<EEntType, EEntType&> AryEtype;
typedef CArray<CItem*, CItem*&> AryItemPtr;
typedef CArray<CWidItem*, CWidItem*&> AryWidItemPtr;
// 当前工程是否为空。
BOOL IsEmptyProject();
// 工程名字
CString ProjectName();
// 工程全路径名称
CString ProjectFullName();
// 得到洞分类的名称 例如:eM ==> “门”
CString Type2Name(EEntType type);
// 门窗类型返回对应的类型名字
CString EntTypeToString(EEntType eEntType);
// 检测某eEntType类型数据是否具有该属性
// BOOL TestHasProp(EEntType eEntType, EShowItem eShowItem);
// 检测id对应实体的属性跟sValue是否相等
BOOL IsPropModify(AcDbObjectId id, EShowItem eShowItem, CString sValue);
// 从数组中查找同名的widItem;
CWidItem* FindWidItem(const AryWidItemPtr &aryWidItem, CString strLabel);
// 向widItem数组中添加pItem
void AddItemToWidItemAry(AryWidItemPtr &aryWidItem, CItem *pItem);
// 清空,并且释放pWidItem对应的内存
void ClearAryWidItemPtr(AryWidItemPtr &aryWidItemPtr);
// AryItemPtr ==> AryWidItemPtr; 本函数直接将每个item ==> widItem.并不执行同名合并。
void ItemPtrAry2Wid(const AryItemPtr &aryItemPtr, AryWidItemPtr &aryWidItem);
// 将当前的属性数据覆盖DWG图纸中的数据
void UpdateProp2DWG(AcDbEntity* pEnt, EEntType eEntType, AryEShowItem &aryEShowItem, CStringArray &aryProp);
// 修改类门窗样式
void UpdateEntStyle(TDbEntity *pEnt, EEntType eEntType, CString strStyle, bool b2dOr3d);
// 鉴别编号是否按照尺寸编号,还是按照顺序编号,不是按照尺寸编号就认为是按照顺序编号,没有其他情况
// ret: TRUE:尺寸编号;FALSE:顺序编号
BOOL CheckName(const CString &strName);
// 获取尺寸编号的尺寸
BOOL GetSize(const CString &strName, CString &strHead, CString &strHei, CString &strWid);
BOOL GetSize(const CString &strName, CString &strHead, double &dHei, double &dWid);
// 根据编号判断对应的类型;该函数一般用于检测文字对应的类型,而不检测普通门窗的编号
EEntType TextLabelType(const CString &strLabelHead);
BOOL TestItemEmpty(const AryItemPtr &aryItemPtr, BOOL bText, BOOL bBlock);
BOOL TestItemEmpty(const AryWidItemPtr &aryItemPtr, BOOL bText, BOOL bBlock);
// 洞口属性
struct SOpeningProp
{
SOpeningProp() : pItem(NULL), bText(false), bBlock(false), bExternBlock(false) {};
CString strLabel; // 编号
int nHei; //高度
int nWid; // 宽度
int nEle; // 底高,老虎窗没有该值
CString strType; // 类型,并非所有的洞都有这个参数
XBayWindow::XBayWinStyle eProWinGeo; // 型式,凸窗属性
int nChuTiaoChang; // 凸窗,和转角窗会有这两个属性
int nTixingkuan; // 只有凸窗才有这两个属性
CString str3DShowStyle; // 门窗显示的三维样式
CString str2DShowStyle; // 门窗显示的二维样式
bool bZJCTuChuang; // 转角凸窗,
bool bText;// 是否文字对象。
bool bBlock; // 是不是属于块内对象(外部参照)
bool bExternBlock; // 是否为 外部参考
CItem *pItem; // 所属的item;
};
// 根据id,获取对应的soprop;
BOOL GetDoorWinProp(AcDbObjectId &id, SOpeningProp &soprop, EEntType &eOpType);
// 获取门窗的按照宽高属性的编号。
CString GetDoorWinSizeLabel(EEntType eEntType, const SOpeningProp &sProp);
// 凸窗型式 ==> 字符串名字
CString GeoType2String(XBayWindow::XBayWinStyle style);
// 字符串名字 ==> 凸窗型式
XBayWindow::XBayWinStyle GeoType2Style(CString &strGeoType);
// 设置属性:
void SetPropData(SOpeningProp &sProp, EShowItem eShowItem, CString strData);
// 将prop相应属性转换为字符串。
CString PropToString(const SOpeningProp &prop, EShowItem eShowItem);
// 测试是否冲突,文字不参与冲突测试。
BOOL TestConflict(EEntType type, const SOpeningProp &sprop1, const SOpeningProp &sprop2);
BOOL TestConflict(CItem *pItem); // 检测该数据内部是否冲突
BOOL TestConflict(CItem *pItem1, CItem *pItem2);
// 分别从aryWidItem 和 pWidItem中找到对应的类型、widItem必须是同类型的才能编号。
int FindEType(AryWidItemPtr &aryWidItem, AryEtype &aryEtype);
int FindEType(CWidItem *pWidItem, AryEtype &aryEtype);
typedef CArray<SOpeningProp, SOpeningProp&> AryOpeningProp;
class CGroup;
class CDataTable;
// 每一个共名字的ID -->同楼层的,或者都是没有楼层的
struct CItem
{
AcDbObjectIdArray aryId; // 该组中的ID们,该ID如果是本土所对应的ID,则一直有效,否则,ID并非一直有效。
AryOpeningProp aryProp; // 该组中的prop们
CString strLabel; // 本组的名字,如果为空,则使用尺寸编号。
EEntType eDoorWinType; // 类型。
CGroup *pGroup; // 所属的group;
BOOL bConflict; // 根据检测范围不同在变的冲突
// 处理sLable == sLabel[X];
// bTextTest:是否检测文字。
CString GetItemName(bool bCheckText, bool bBlock) const;
// 非文字的个数。
int NoTextDataNum() const;
// 根据是否检测文字
int ItemNum(bool bText, bool bBlock) const ;
bool HasItem(bool bText, bool bBlock) const;
// 添加属性,并且检测是否冲突。
void AddProp(SOpeningProp &prop);
// 检测某个block是不是重复的
bool TestRepeatBlock(int index) const; //
};
// 对CItem的包装,用于提取信息,不用于数据存储
struct CWidItem
{
CWidItem() : strLabel(_T("")){}
CWidItem(CItem* pItem)
{
AddItem(pItem);
}
// 所有的item
AryItemPtr aryItem; // 所包含的aryItem;
CString strLabel; // 对应的编号
// BOOL bConflict; // 是否冲突
void CopyFrom(const CWidItem &widItem);
int GetEntNum(bool bCheckText, bool bBlock) const;
// 会设置bConflict;
void AddItem(CItem* pItem);
// 处理sLable == sLabel[X];
CString GetItemName(bool bCheckText, bool bBlock) const;
CString StyleString(BOOL is2D) const; // 返回3D门窗样式,如果冲突则返回空
// 检测某个block是不是重复的,检测之前是不是已经存在了。
bool TestRepeatBlock(int nItem, int index) const;
void GetIdAry(TDPtrList<AcDbObjectId> &idLst);
};
// 一组数据,包含所有类型,用来代表一个楼层
class CGroup
{
public:
CGroup();
~CGroup();
void Clear();
// 按照类型添加门窗,返回门窗对应的check指针
// 同名,同类型,放在同一个下边,注意监测冲突标记
CItem* AddOpening(AcDbObjectId &id, SOpeningProp &prop, EEntType eEntType);
// 获取、设置楼层名字
CString GetFloorName() const;
void SetFloorName(CString strName);
// 是否当前文档
BOOL IsCurrDoc() const;
// 根据类型获取CheckItem;
const AryItemPtr& GetItemAry(EEntType eEntType)const;
// 本楼层包含的对象类型
int FindEType(AryEtype &aryEType) const;
// 过滤ID
void FilterId(AcDbObjectIdArray &idArray);
private:
CString m_strFloor; // 楼层名字
public:
AryItemPtr m_doors[eDoorTypeNum];
BOOL m_bCurrDoc; // 是否当前图
CDataTable *m_pDataTable;
};
typedef CArray<CGroup*, CGroup*> AryAllData;
// 保存工程数据,用以检测工程是否发生改变
struct SProjectInfo
{
struct _SFloorInfo
{
CString strfloorNo;
CString strFloorDoc;
XPoint ptMin;
XPoint ptMax;
bool bInFrame;
};
CString strProjectName;
CString strProjectFullName;
CArray<_SFloorInfo, _SFloorInfo> aryFloorInfo;
// DList<XFloorData> lstFloorData;
void Clear();
void Init();
void AddFloorInfoByDoc(CString _strFloorNo, CString _strFloorDoc);
void AddFloorByRange(CString _strFloorNo, CString _strFloorDoc, XPoint _ptMin, XPoint _ptMax);
// 比较,没有差异的话,返回true.否则返回false;
bool Compare(const SProjectInfo &sProjectInfo) const;
void ReadProjInfo();
};
// 门窗检查数据结构
class CDataTable
{
struct _DataStruct
{
AcDbObjectId id;
SOpeningProp *prop;
EEntType eEntType;
};
typedef CArray<_DataStruct, _DataStruct&> _AryDataStruct;
public:
CDataTable();
virtual ~CDataTable();
void Clear();
// 是否空工程。
BOOL IsEmptyTable() const;
BOOL IsProjChange() const; // 检测当前工程是否发生改变;
BOOL IsDocChange() const; // 检测当前工程是否发生改变;
bool IsCurrDocNotInProj() const;
// 根据楼层添加ID。nFloor是GetFloorTable()中的索引顺序,并非真正的楼层编号
void AddIdByFloor(AcDbObjectIdArray &idAry, int nFloor, CString &floorName, BOOL bCurrDoc = FALSE, AcDbObjectIdArray *pAryIdBlock = NULL);
// 添加不属于工程的数据,只有当前图才考虑添加不属于工程的数据
void AddIdNoProject(AcDbObjectIdArray &idAry, AcDbObjectIdArray *pAryIdBlock = NULL);
void SetFloorNum(int n); // 设置楼层的个数
// 框选标记设置,标记当前结果是框选结果。
bool IsSelData() const {return m_bSelBox;}
void SetSelFlag(bool bSel) {m_bSelBox = bSel;}
// 获取楼层数
int GetFloorNum() const;
// 获取楼层
CGroup* GetFloor(int nFloor) const;
// 工程名、工程全名、当前文档名的设置和读取。
void SetProjName(CString sProjName) {m_projectInfo.strProjectName = sProjName;}
CString GetProjName() const {return m_projectInfo.strProjectName;}
void SetProjFullName(CString sProjFullName) {m_projectInfo.strProjectFullName = sProjFullName;}
CString GetProjFullName() const {return m_projectInfo.strProjectFullName;}
void SetDocName(CString sDoc) {m_strCurrDoc = sDoc;}
CString GetDocName() const {return m_strCurrDoc;}
//////////////////////////////////////////////////////////////////////////
// 属性表格绘制
// 本工程的数据包含的所有的门窗类型,工程内
int FindETypeProj(AryEtype &aryEType) const;
// 本工程,本图内的数据包含的所有的门窗类型
int FindETypeDwg(AryEtype &aryEtype) const;
// 本工程,本图内的数据包含的所有的门窗类型
int FindETypeNoProj(AryEtype &aryEtype) const;
static int FindEType(AryWidItemPtr widItemPtr[eDoorTypeNum], AryEtype &aryEtype);
// 判断有没有未创建工程的数据
BOOL HasNoProjData() const;
// 本工程内的所有的数据,不分楼层。
void GetDataPNf(AryWidItemPtr doors[eDoorTypeNum]) const;
// void GetNoFloorCurrProj(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ???????本工程的所有数据,分楼层
void GetDataPF(AryAllData &data) const;
// ???????本工程的冲突数据,
void GetConflictProj(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ????????工程内本图的数据,分楼层
void GetDataDPF(AryAllData &data) const;
// ????????工程内本图的数据,不分楼层
void GetCurrDPNf(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ????????工程内本图的冲突数据,不分楼层
void GetConflictDP(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ????????全部本图的数据,不分楼层
void GetDataDNpNf(AryAllData &data) const;
void GetDataDNpNf(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ????????全部本图的冲突数据
void GetConflictDNp(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ????????工程外的数据
const CGroup* GetDataNp() const {return &m_dataNoProject;}
void GetDataNp(AryWidItemPtr widItem[eDoorTypeNum]) const;
// ????????工程外的冲突数据
void GetConflictNoProj(AryWidItemPtr widItem[eDoorTypeNum]) const;
// 根据当前的形式计算冲突数据,在CItem中设置标记
void CalcConflictData();
// 属性表格绘制
//////////////////////////////////////////////////////////////////////////
// 数据更新检测:
enum EDataChange {eProjChange = 0x01, eDocChange = 0x02, eLabelChange = 0x04,
eIdAdd = 0x8, eIdDel = 0x10, ePropChange = 0x20};
DWORD Compare(const CDataTable &dataTable) const;
// 检测数据的改变,标签改变,id添加,id删除,属性改变
DWORD DataCompare(const CDataTable &dataTable, bool bOnlyDWG, bool bOnlyProj, bool bNeedText, bool bNeedBlock) const;
static BOOL TestDataChange(const DWORD dwFlag, EDataChange eChange);
static void SetDataChange(DWORD &dwFlag, EDataChange eChange, BOOL bSet);
// 更新属性:更新属性中除了编号之外的其他内容,只更新当前文档
void UpdateProp(const CDataTable &dataTable);
// 筛选,筛选出处于ss中的数据,其他数据删除,该函数用于框选
void FilterId(AcDbObjectIdArray &idArray);
// 查找未编号门窗的个数
int GetNoNameLabeNum(bool bOnlyDWG, bool bOnlyProj, bool bNeedText, bool bNeedBlock) const;
// 检测数据是否为空。
// true:不空,false:空
bool TestHasData(bool bOnlyDWG, bool bOnlyProj, bool bNeedText, bool bNeedBlock) const;
// 是否定义楼层:true:有楼层,False没有楼层
bool HasFloor() const;
// 检测是否有未创建工程的数据。
bool TestHasNoProjData(bool bNeedText, bool bNeedBlock) const;
// 再更新了原图数据之后,现在保存的数据即变成了老数据,如果重新提取图形,一定要把老数据更新掉,
void MakeDataOld() {m_bOldData = true;}
bool IsOldData() const {return m_bOldData;}
void SetFileInfo();
void ClearNullFloor();
void AddFloorInfo(CString strFloorNo, CString strFloorDoc, bool bInFrame, const XPoint &ptMin, const XPoint &ptMax);
protected:
// 清空aryData的内容,包括内部的释放内存
static void ClearFloorDataAry(AryAllData &aryData);
static SOpeningProp* GetProp(_AryDataStruct &_aryDataStruct, const AcDbObjectId &id);
// dataStruct根据编号的比较函数。
static int Cmp_DataStruct(const void *ds1, const void *ds2);
void GetAryDataStruct(_AryDataStruct &aryDataStruct, bool bOnLyDWG, bool bOnLyProj, bool bNeedText, bool bNeedBlock)const;
private:
AryAllData m_aryDataAll; // 已创建工程数据
CGroup m_dataNoProject; // 本图未创建工程数据,或者没有工程的时候
// CString m_strProjName; // 工程名称,纯工程名字。没有后缀
// CString m_strProjFullName; // 工程全路径名称,// 防止切换
CString m_strCurrDoc; // 当前图纸全路径名称,防止切换了原图
bool m_bSelBox; // 框选结果
bool m_bOldData; // 老数据标志,如果数据被更新到原图之后,当前数据已经过期,如果发生提取图纸命令,则重新提取数据
SProjectInfo m_projectInfo; // 工程信息,需要检测工程是否发生改变,如果需要发生改变,则需要重新显示数据
};
// 获取门窗列表
void FilterDoorWinText(DList<AcDbObjectId> &lstId);
void GetOpeningIdListNew(DList<AcDbDatabase> &dbList, DList<AcDbObjectId> &idList);
void GetCurrProjAndDoc(CString &strCurrProj, CString &strCurrDoc, CString &strCurrProjFullName);
// 读取本土中的门窗ID。
// lstIdAll:所有的ID。aryIdBlock:块表中的ID
void GetDoorWinIds(DList<AcDbObjectId> &lstIdAll, AcDbObjectIdArray &aryIdBlock);
void GetOpeningDataTable(CDataTable &dataTable);
template <class T>
BOOL IsEmpty(const T &ary)
{
return (ary.GetSize() == 0);
}
template <class T>
BOOL IsEmptyAcAry(const T &ary)
{
return (ary.length() == 0);
}
};
// 附带冲突检测的逻辑:
// 根据当前显示范围的不同,以及显示的属性的不同,冲突检测的结果不同。
// 冲突检测执行以下逻辑:
// 每次重新生成的时候,根据当前属性,执行检测设置冲突标记。
// 绘制的时候,直接检测冲突标记是否设置。