428 lines
17 KiB
C++
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);
|
|
}
|
|
};
|
|
|
|
// 附带冲突检测的逻辑:
|
|
// 根据当前显示范围的不同,以及显示的属性的不同,冲突检测的结果不同。
|
|
// 冲突检测执行以下逻辑:
|
|
// 每次重新生成的时候,根据当前属性,执行检测设置冲突标记。
|
|
// 绘制的时候,直接检测冲突标记是否设置。
|