Compare commits

..
20 Commits
Author SHA1 Message Date
gjm 806726c11b Merge pull request 'fix: HLR 退化圆弧按来源实体直径判断,并支持爬梯' (#12) from home-lenovo-legion-r9000/fix/aecdbcamera-fitting-degenerate-arc into main
Reviewed-on: #12
2026-10-16 23:22:22 +08:00
gjm bbb899c0a0 fix: HLR 退化圆弧按来源实体直径判断,并支持爬梯
在删除圆心角为 PI 的退化圆弧时,增加直径比较:
- 弯头(eElbow / eReduceElbow):带法兰(连接类型 3/5)取法兰外径 m_dInterfaceD,
  否则取画法直径 m_dD;
- 爬梯(AecDbClimbStair):取踏管直径 ClimbStair::dd。
仅当圆弧直径大于来源实体直径时才删除。

getElbowDiameter 改为 getSourceDiameter,removeFittingDegenerateArcs
改为 removeDegenerateArcs(已不止管件)。
2026-10-16 23:20:57 +08:00
gjm 775b3c181c Merge pull request 'fix: HLR 结果中删除 AecDbEwFitting 产生的退化圆弧' (#11) from home-lenovo-legion-r9000/fix/aecdbcamera-fitting-degenerate-arc into main
Reviewed-on: #11
2026-10-16 21:34:50 +08:00
gjm c0c04952dc fix: HLR 结果中删除 AecDbEwFitting 产生的退化圆弧
原 isDegenerateArc 以 弧长/半径 比值判断退化圆弧,且无法区分结果来源。
改为按来源实体类型判断:
- result1 的键是数据库实体 id,直接判断该 id 是否为 AecDbEwFitting;
- result2 的键是无 id 的补充实体指针,先经 mpAdditional
  (数据库实体id -> 其产生的补充实体) 反查归属的数据库实体 id,再判断。

删除规则:结果实体是 AcDbArc 且圆心角为 PI 时删除。
2026-10-16 21:34:08 +08:00
gjm c41e7edf44 Merge pull request 'docs: 更正远端地址为 envi-code 仓库,补充 SSH 私钥本机配置说明' (#10) from home-lenovo-legion-r9000/docs/fix-remote-url into main
Reviewed-on: #10
2026-10-16 19:44:45 +08:00
gjm 35a412f6f5 docs: 更正远端地址为 envi-code 仓库,补充 SSH 私钥本机配置说明
- 远端由 ssh://gjm@47.93.46.28:1216/srv/git/new-start.git
  更正为 ssh://git@39.107.55.179:222/gjm/envi-code.git
- 补充说明:远端走 SSH 222 端口,各机器私钥不同,
  需在本机 ~/.ssh/config 指定;私钥文件名不入库
2026-10-16 19:39:29 +08:00
gjm c4569ecac3 Merge pull request 'fix(HLR): 清理剖切结果中的退化圆弧,避免圆心角溢出生成反向大圆弧' (#9) from company-desktop-computer/company-ai-dev into main
Reviewed-on: #9
2026-10-16 13:12:43 +08:00
company-desktop-computer a1c7d39dc6 fix(HLR): 清理剖切结果中的退化圆弧,避免圆心角溢出生成反向大圆弧
AecDbXCamera::hlrCalc 在 HLR 计算后新增 isDegenerateArc 判定:结果为 AcDbArc 且 弧长/半径 < 1e-6 时视为退化圆弧(圆心角极小),从 result1/result2 中删除,防止数值溢出把"很小一段"翻转成"反向的大圆弧"。
2026-10-16 13:11:21 +08:00
gjm fdfb6e5bbb Merge pull request 'chore: 忽略 *.aps,并修正 JSTZDlg 矩阵列显示' (#8) from company-desktop-computer/company-ai-dev into main
Reviewed-on: #8
2026-10-13 15:33:07 +08:00
company-desktop-computer 1db5368592 chore: 忽略 *.aps,并修正 JSTZDlg 矩阵列显示
- .gitignore 增加 *.aps(EarthWorm.aps 等 VS 资源编译产物)。
- JSTZDlg::ShowToCompareList 的矩阵分支改用 AecDbObjXDataMap::MatrixToString(),
  不再直接把 pszVal 当字符串打印(矩阵现以二进制块保存)。
2026-10-13 15:32:29 +08:00
gjm 4961b696ff Merge pull request '重构: AecDbObjXDataMap 解耦 UI,并统一 SetAt/数组实现' (#7) from company-desktop-computer/company-ai-dev into main
Reviewed-on: #7
2026-10-13 15:29:26 +08:00
company-desktop-computer 199abb989c 重构: AecDbObjXDataMap 解耦 UI,并统一 SetAt/数组实现
- AecXData 的 ctor/Free/CopyFrom 由头部 inline 移入 .cpp,结构体加
  AECDLLIMPEXP 导出,修复其它模块构造 AecXData 时的 LNK2019。
- 抽出私有 SetXData(pszKey, xdata) 助手,替换各 SetAt 中重复的
  find/Free+覆盖/insert 逻辑,并接管 xdata 所有权。
- 数组二进制块统一为 [kArrayMagic][元素类型][元素个数][数据...],元素类型
  复用 AecXData::EType;新增元素类型无需再加魔数或类型标签。
- 矩阵/数组魔数集中到 .cpp 顶部常量,便于维护。
- List(CListCtrl*, int) 改为 List(std::vector<CString>&):去掉 MFC 控件与
  nImage 依赖,每个元素输出 key/value 两项;CCKSXDlg::ListXDataMap 相应改为
  构造 vector 后填充两列列表。
2026-10-13 15:28:19 +08:00
gjm 7f2f37f005 Merge pull request '重构: AecXData 类型标签改用枚举 AecXData::EType' (#6) from company-desktop-computer/company-ai-dev into main
Reviewed-on: #6
2026-10-13 10:01:14 +08:00
company-desktop-computer 0467086e65 重构: AecXData 类型标签改用枚举 AecXData::EType
- 在 AecXData 内新增 enum EType,取值直接采用 wtypes.h 的 VARENUM(VT_*),
  与原实现逐位一致(nVt 会序列化进 DWG/DXF/XData,数值必须保持不变)。
- 各模块共 303 处 nVt 判断由裸 VT_* 改为 AecXData::kTypeXxx,涉及 18 个文件;
  仅调试打印用的字符串字面量保持原样。
- AecDbObjXDataMap.h 增加 #include <wtypes.h>(EType 引用 VT_*)。
2026-10-13 09:55:42 +08:00
gjm 63ed4744fb Merge pull request 'fix(FlangeDlg): 修正 GetEndF1/GetEndF2 端面取值下标' (#5) from company-desktop-computer/company-ai-dev into main
Reviewed-on: #5
2026-10-09 14:12:16 +08:00
company-desktop-computer 9d9077a03e fix(FlangeDlg): 修正 GetEndF1/GetEndF2 端面取值下标
- CFlangeDlg::GetEndF1/GetEndF2 原先取 m_arFlangeVals 下标 0/1(公称直径/法兰外径),
  端面型式实际在下标 5/6,导致 PIPE_FLANGF 被写成 DN 字符串
- 改为下标 5/6,且为空时回退 "FF"
2026-10-09 14:09:23 +08:00
gjm 8628fcc7e0 Merge pull request 'test: 验证 company-desktop-computer 账号的 PR 作者' (#4) from company-desktop-computer/pr-test-company into main
Reviewed-on: #4
2026-10-09 10:48:18 +08:00
gjm b7b9827994 test: 验证 company-desktop-computer 账号的 PR 作者 2026-10-09 10:46:59 +08:00
gjm b96cb1bed2 Merge pull request '法兰双击改用法兰对话框:AecDbEwFitting 法兰双击弹出 CFlangeDlg 并回写法兰/垫片数据' (#3) from home-lenovo-legion-r9000/company-ai-dev into main
Reviewed-on: #3
2026-10-09 10:33:03 +08:00
gjm d107cfd47f 法兰双击改用法兰对话框:AecDbEwFitting 法兰双击弹出 CFlangeDlg 并回写法兰/垫片数据
- DBL_AEC_DBEWFIT:GetFittingType()==eFlange 时改用 CFlangeDlg(其余管件仍用 CGJSXDlg)
- 对话框初值取自实体专业数据(DN/压力/等级/项目/外径系列)
- 确定后回写 PIPE_WD/PIPE_WTHICK/PIPE_THICK/PIPE_N/PIPE_FLANGF 及垫片数据并重绘
- 沿用接口位移后收缩相邻管段逻辑
2026-10-09 10:31:04 +08:00
26 changed files with 1346 additions and 971 deletions

No files matched your search

+11
View File
@@ -3,3 +3,14 @@ ZRX/
cmake_output/
bin/
lib/
*.dwg
*.png
*.dwl
*.dwl2
*.pdf
*.pcf
*.bat
*.scr
*.py
*.tmp
*.aps
+2 -1
View File
@@ -10,7 +10,8 @@ This file provides guidance to CodeBuddy Code when working with code in this rep
- **形态**:ObjectARX / ZRX 插件(DLL,后缀 `.arx` / `.zrx`),运行在 CAD 宿主内,含大量 MFC 界面与自定义图元实体。
- **CMake 项目名**:`SHS_Code2026`(version 1.0.0)。
- **主代码目录**:`SourceCode/Code2026/`(C++ 约 2888 `.cpp` + 3104 `.h`;另有天正 `tg_shs/` 系列库)。
- **远端**:`origin` = `ssh://gjm@47.93.46.28:1216/srv/git/new-start.git`,主分支 `main`。提交信息用中文。
- **远端**:`origin` = `ssh://git@39.107.55.179:222/gjm/envi-code.git`,主分支 `main`。提交信息用中文。
- **SSH**:远端走 SSH 222 端口,需在本机 `~/.ssh/config` 或 ssh-agent 中指定可用私钥(各机器私钥不同,**不要把私钥文件名写进仓库**)。
目标平台(由 preset 与编译宏区分):
@@ -800,7 +800,7 @@ Acad::ErrorStatus AecDbCurveBase::subDeepClone( AcDbObject* pOwner,
for (; it != end; )
{
if (!pXDataMap->GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_UI4 || cVal.nVt == VT_UI8)//soft,hard
if (cVal.nVt == AecXData::kTypeSoftId || cVal.nVt == AecXData::kTypeHardId)//soft,hard
{
idSrc.setFromOldId(cVal.nVal);
@@ -820,7 +820,7 @@ Acad::ErrorStatus AecDbCurveBase::subDeepClone( AcDbObject* pOwner,
if (pXDataMapCloned != NULL)
{
pXDataMapCloned->RemoveAt(sKey);
pXDataMapCloned->SetAt(sKey,idPair2.value(),cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey,idPair2.value(),cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
continue;
}
@@ -880,7 +880,7 @@ Acad::ErrorStatus AecDbCurveBase::subDeepClone( AcDbObject* pOwner,
if (idCloned.isValid())
{
pXDataMapCloned->RemoveAt(sKey);
pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
else
{
@@ -888,7 +888,7 @@ Acad::ErrorStatus AecDbCurveBase::subDeepClone( AcDbObject* pOwner,
}
}
}
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
arHandKeys.Add(sKey);
}
@@ -1253,7 +1253,7 @@ Acad::ErrorStatus AecDbCurveBase::subWblockClone(AcRxObject* pOwner,
for (; it != end;)
{
if (!pXDataMap->GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_UI4 || cVal.nVt == VT_UI8)//soft,hard
if (cVal.nVt == AecXData::kTypeSoftId || cVal.nVt == AecXData::kTypeHardId)//soft,hard
{
idSrc.setFromOldId(cVal.nVal);
@@ -1272,7 +1272,7 @@ Acad::ErrorStatus AecDbCurveBase::subWblockClone(AcRxObject* pOwner,
{
if (pXDataMapCloned != NULL)
{
pXDataMapCloned->SetAt(sKey,idPair2.value(),cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey,idPair2.value(),cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
continue;
}
@@ -1321,10 +1321,10 @@ Acad::ErrorStatus AecDbCurveBase::subWblockClone(AcRxObject* pOwner,
if (pXDataMapCloned != NULL)
{
pXDataMapCloned->RemoveAt(sKey);
pXDataMapCloned->SetAt(sKey,idCloned,cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey,idCloned,cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
}
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
arHandKeys.Add(sKey);
}
@@ -752,7 +752,7 @@ Acad::ErrorStatus AecDbEntityBase::subDeepClone( AcDbObject* pOwner,
for (; it != end; )
{
if (!pXDataMap->GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_UI4 || cVal.nVt == VT_UI8)//soft,hard
if (cVal.nVt == AecXData::kTypeSoftId || cVal.nVt == AecXData::kTypeHardId)//soft,hard
{
idSrc.setFromOldId(cVal.nVal);
@@ -772,7 +772,7 @@ Acad::ErrorStatus AecDbEntityBase::subDeepClone( AcDbObject* pOwner,
if (pXDataMapCloned != NULL)
{
pXDataMapCloned->RemoveAt(sKey);
pXDataMapCloned->SetAt(sKey, idPair2.value(), cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey, idPair2.value(), cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
continue;
}
@@ -832,7 +832,7 @@ Acad::ErrorStatus AecDbEntityBase::subDeepClone( AcDbObject* pOwner,
if (idCloned.isValid())
{
pXDataMapCloned->RemoveAt(sKey);
pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
else
{
@@ -840,7 +840,7 @@ Acad::ErrorStatus AecDbEntityBase::subDeepClone( AcDbObject* pOwner,
}
}
}
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
arHandKeys.Add(sKey);
}
@@ -1207,7 +1207,7 @@ Acad::ErrorStatus AecDbEntityBase::subWblockClone(AcRxObject* pOwner,
for (; it != end;)
{
if (!pXDataMap->GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_UI4 || cVal.nVt == VT_UI8)//soft,hard
if (cVal.nVt == AecXData::kTypeSoftId || cVal.nVt == AecXData::kTypeHardId)//soft,hard
{
idSrc.setFromOldId(cVal.nVal);
@@ -1226,7 +1226,7 @@ Acad::ErrorStatus AecDbEntityBase::subWblockClone(AcRxObject* pOwner,
{
if (pXDataMapCloned != NULL)
{
pXDataMapCloned->SetAt(sKey, idPair2.value(), cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey, idPair2.value(), cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
continue;
}
@@ -1276,10 +1276,10 @@ Acad::ErrorStatus AecDbEntityBase::subWblockClone(AcRxObject* pOwner,
if (pXDataMapCloned != NULL)
{
pXDataMapCloned->RemoveAt(sKey);
pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == VT_UI4 ? TRUE : FALSE);
pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE);
}
}
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
arHandKeys.Add(sKey);
}
File diff suppressed because it is too large. Load diff
+13 -3
View File
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "CCKSXDlg.h"
#include "AecDbObjXDataMap.h"
#include <vector>
IMPLEMENT_DYNAMIC(CCKSXDlg, CDialog)
@@ -77,10 +78,19 @@ BOOL CCKSXDlg::OnInitDialog()
void CCKSXDlg::ListXDataMap(AecDbObjXDataMap *pXDataMap)
{
if (pXDataMap != NULL)
if (pXDataMap == NULL)
return;
m_wndListXData.DeleteAllItems();
std::vector<CString> vecItems;
pXDataMap->List(vecItems);
// List() 每个元素输出两项:先 key(名称列),后 value(数据列)。
for (size_t i = 0; i + 1 < vecItems.size(); i += 2)
{
m_wndListXData.DeleteAllItems();
pXDataMap->List(&m_wndListXData, 0);
int nItem = m_wndListXData.InsertItem(m_wndListXData.GetItemCount(), vecItems[i]);
m_wndListXData.SetItemText(nItem, 1, vecItems[i + 1]);
}
}
+13 -13
View File
@@ -2668,11 +2668,11 @@ void CJSTZDlg::ShowToCompareList(LPCTSTR pszName,AecDbObjXDataMap& map1,AecDbObj
nVt = xdata1.nVt;
switch (nVt)
{
case VT_I4: // 整型
case AecXData::kTypeInt: // 整型
sVal1.Format(_T("%d"),(int)xdata1.nVal);
sVal2.Format(_T("%d"),(int)xdata2.nVal);
break;
case VT_UI4: //s id
case AecXData::kTypeSoftId: //s id
#ifndef _WIN64
sVal1.Format(_T("%ld"),xdata1.nVal);
sVal2.Format(_T("%ld"),xdata2.nVal);
@@ -2681,7 +2681,7 @@ void CJSTZDlg::ShowToCompareList(LPCTSTR pszName,AecDbObjXDataMap& map1,AecDbObj
sVal2.Format(_T("%d"),xdata2.nVal);
#endif
break;
case VT_UI8: //h id
case AecXData::kTypeHardId: //h id
#ifndef _WIN64
sVal1.Format(_T("%ld"),xdata1.nVal);
sVal2.Format(_T("%ld"),xdata2.nVal);
@@ -2690,33 +2690,33 @@ void CJSTZDlg::ShowToCompareList(LPCTSTR pszName,AecDbObjXDataMap& map1,AecDbObj
sVal2.Format(_T("%d"),xdata2.nVal);
#endif
break;
case VT_R8: // 浮点
case AecXData::kTypeDouble: // 浮点
sVal1.Format(_T("%.3f"),xdata1.dVal[0]);
sVal2.Format(_T("%.3f"),xdata2.dVal[0]);
break;
case (VT_BYREF | VT_R8): // 点
case AecXData::kTypePoint: // 点
sVal1.Format(_T("%.3f,%.3f,%.3f"),xdata1.dVal[0],xdata1.dVal[1],xdata1.dVal[2]);
sVal2.Format(_T("%.3f,%.3f,%.3f"),xdata2.dVal[0],xdata2.dVal[1],xdata2.dVal[2]);
break;
case (VT_BYREF | VT_R8 + 1): // cad变化点
case AecXData::kTypePointWorld: // cad变化点
sVal1.Format(_T("%.3f,%.3f,%.3f"),xdata1.dVal[0],xdata1.dVal[1],xdata1.dVal[2]);
sVal2.Format(_T("%.3f,%.3f,%.3f"),xdata2.dVal[0],xdata2.dVal[1],xdata2.dVal[2]);
break;
case (VT_BYREF | VT_R8 + 2): // 向量
case AecXData::kTypeVector: // 向量
sVal1.Format(_T("%.3f,%.3f,%.3f"),xdata1.dVal[0],xdata1.dVal[1],xdata1.dVal[2]);
sVal2.Format(_T("%.3f,%.3f,%.3f"),xdata2.dVal[0],xdata2.dVal[1],xdata2.dVal[2]);
break;
case (VT_BYREF | VT_R8 + 3): // 变化向量
case AecXData::kTypeVectorWorld: // 变化向量
sVal1.Format(_T("%.3f,%.3f,%.3f"),xdata1.dVal[0],xdata1.dVal[1],xdata1.dVal[2]);
sVal2.Format(_T("%.3f,%.3f,%.3f"),xdata2.dVal[0],xdata2.dVal[1],xdata2.dVal[2]);
break;
case (VT_BYREF | VT_R8 + 4): // 矩阵
sVal1.Format(_T("%s"),xdata1.pszVal);
sVal2.Format(_T("%s"),xdata2.pszVal);
case AecXData::kTypeMatrix: // 矩阵
sVal1 = AecDbObjXDataMap::MatrixToString(xdata1);
sVal2 = AecDbObjXDataMap::MatrixToString(xdata2);
break;
case (VT_BYREF | VT_R8 + 5): // binarydata
case AecXData::kTypeBinary: // binarydata
break;
case VT_BSTR: // 字符串
case AecXData::kTypeString: // 字符串
sVal1.Format(_T("%s"),xdata1.pszVal);
sVal2.Format(_T("%s"),xdata2.pszVal);
break;
+1 -1
View File
@@ -261,7 +261,7 @@ namespace
for (AecDbObjXDataMap::It it = pMap->Begin(); it != pMap->End(); ++it)
{
const AecXData &xd = it->second;
if (xd.nVt == VT_BSTR && xd.pszVal)
if (xd.nVt == AecXData::kTypeString && xd.pszVal)
{
CString s(xd.pszVal);
s.Trim();
@@ -937,12 +937,12 @@ BOOL AecDbAssembleWell::CalValue(const CString &sExp,double& dRes) const
break;
//替换
if (cVal.nVt == VT_I4)
if (cVal.nVt == AecXData::kTypeInt)
{
cal.SetVariableData(sKey, 1.0 * cVal.nVal);
}
if (cVal.nVt == VT_R8)
if (cVal.nVt == AecXData::kTypeDouble)
{
cal.SetVariableData(sKey, cVal.dVal[0]);
}
@@ -6,6 +6,8 @@
#include "CoreTools.h"
#include "HlrCutOption.h"
#include "aecdbewpipebase.h"
#include "AecDbEwFitting.h"
#include "AecDbClimbStair.h"
#include "compare_double.h"
#include "simpleproperty.h"
#include "hlrcommands.h"
@@ -534,6 +536,133 @@ namespace
//#endif
}
// 取得指定 id 对应实体用于与 HLR 结果圆弧比较的"直径"。目前处理两类来源:
// 弯头(eElbow / eReduceElbow):带法兰(连接类型 3 法兰管 / 5 法兰管线)时取法兰外径,
// 否则取弯头画法直径;
// 爬梯(AecDbClimbStair):取踏管直径。
// 其他实体返回 false(不处理)。
bool getSourceDiameter(const AcDbObjectId &id, double &dDiameter)
{
dDiameter = 0.0;
if (id == AcDbObjectId::kNull)
return false;
AcDbEntityPointer ent(id, AcDb::kForRead);
if (ent.openStatus() != Acad::eOk)
return false;
AcDbEntity *pEnt(ent);
// 爬梯:踏管直径
AecDbClimbStair *pStair(AecDbClimbStair::cast(pEnt));
if (pStair != NULL)
{
ClimbStair data;
memset(&data, 0, sizeof(ClimbStair));
pStair->GetClimbStairData(data);
dDiameter = data.dd;
return true;
}
// 弯头
AecDbEwFitting *pFit(AecDbEwFitting::cast(pEnt));
if (pFit == NULL)
return false;
const EFittingType eType(pFit->GetFittingType());
if (eType != eElbow && eType != eReduceElbow)
return false;
WPipe::PipeParam *pParam(pFit->GetPipeParam());
if (pParam == NULL)
return false;
const bool bFlange(pParam->m_nConnectType == 3 || pParam->m_nConnectType == 5);
dDiameter = bFlange ? pParam->m_dInterfaceD : pParam->m_dD;
delete pParam;
return true;
}
// 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 isDegenerateSourceArc(AcDbEntity *pEnt, const double &dSourceDiameter)
{
AcDbArc *pArc(AcDbArc::cast(pEnt));
if (pArc == NULL)
return false;
if (!COMPARE_DOUBLE::equal(pArc->totalAngle(), PI, 1e-9))
return false;
if (dSourceDiameter <= 1.e-6) // 取不到来源直径,无法比较,不删除
return false;
return COMPARE_DOUBLE::up_zero(pArc->radius() * 2.0 - dSourceDiameter, 1e-6);
}
// 删除 result1 / result2 中由弯头或爬梯经 HLR 计算产生的退化圆弧。
// result1 的键是数据库实体 id,直接取该 id 对应实体的直径;
// result2 的键是无 id 的补充实体指针,需经 mpAdditional 反查归属的数据库实体 id 再取直径。
void removeDegenerateArcs(IDMapEntities &result1
, EntMapEntities &result2
, const IDMapEntities &mpAdditional)
{
IDMapEntities::iterator it(result1.begin());
for (; it != result1.end(); ++it)
{
double dDiameter(0.0);
if (!getSourceDiameter(it->first, dDiameter))
continue;
for (int i(it->second.length() - 1); i >= 0; --i)
{
if (isDegenerateSourceArc(it->second[i], dDiameter))
{
delete it->second[i];
it->second.removeAt(i);
}
}
}
EntMapEntities::iterator it2(result2.begin());
for (; it2 != result2.end(); ++it2)
{
double dDiameter(0.0);
if (!getSourceDiameter(fittingIdOfResultKey(it2->first, mpAdditional), dDiameter))
continue;
for (int i(it2->second.length() - 1); i >= 0; --i)
{
if (isDegenerateSourceArc(it2->second[i], dDiameter))
{
delete it2->second[i];
it2->second.removeAt(i);
}
}
}
}
bool zeroLength(AcDbCurve *pCrv, const double &tol)
{
double dPEnd(.0), dDist(.0);
@@ -1966,6 +2095,9 @@ void AecDbXCamera::hlrCalc(AcDbObjectIdArray &arIds
HlrCalc(arIds, arAdditional_all, pVp.get(), control, result1, result2);
// 删除由弯头或爬梯经 HLR 计算产生的退化圆弧(圆心角溢出为 PI)。
removeDegenerateArcs(result1, result2, mpAdditional);
if (result1.empty() && result2.empty())
{
// 如果实体的PreprocessForHlr函数内,设置了 HLR_CALC,从而影响实体的 Draw3d 函数的返回
@@ -1756,7 +1756,7 @@ Acad::ErrorStatus AecDbEwPipe::TransformHole(const AcGeMatrix3d& xform)
for (; it != end;)
{
if (!m_mapSpecXData.GetNext(it, sKey, cVal)) break;
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
@@ -1661,7 +1661,7 @@ void AecDbEwPipeBase::GetAssocHandleObjs(AcDbObjectIdArray& arIds)
for (; it != end;)
{
if (!m_mapSpecXData.GetNext(it, sKey,cVal)) break;
if ( sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR )//可能的实体句柄
if ( sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString )//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
@@ -1826,7 +1826,7 @@ Acad::ErrorStatus AecDbEwPipeBase::subTransformBy(const AcGeMatrix3d& xform)
for (; it != end;)
{
if (!m_mapSpecXData.GetNext(it, sKey, cVal)) break;
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
@@ -240,7 +240,7 @@ void HlrCutOption::ProcessHlrResult(const AcDbEntity *pE
std::vector<CString> strs;
for (AecDbObjXDataMap::It it = testData.Begin(); it != testData.End(); ++it)
{
if (it->second.nVt == (VT_BYREF | VT_R8 + 5))
if (it->second.nVt == AecXData::kTypeBinary)
strs.push_back(it->first);
}
for (size_t i(0); i < strs.size(); ++i)
@@ -875,12 +875,12 @@ BOOL AecDbPipeHanger::CLC(CString &sTxt)
for (; it != end; )
{
m_mapSpecXData.GetNext(it, sKey, xData);
if (xData.nVt == VT_UI4 ||
xData.nVt == VT_I4)
if (xData.nVt == AecXData::kTypeSoftId ||
xData.nVt == AecXData::kTypeInt)
{
cal.SetVariableData(sKey, 1.0 * xData.nVal);
}
else if (xData.nVt == VT_R8)
else if (xData.nVt == AecXData::kTypeDouble)
{
cal.SetVariableData(sKey, xData.dVal[0]);
}
@@ -2318,7 +2318,7 @@ void AecDbECableLine::RemoveHolePipe(AecDbECableTray* pWPipe)
for (; it != end;)
{
if (!pXDatMap->GetNext(it, sKey, cVal)) break;
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
@@ -2888,7 +2888,7 @@ void AecDbDuctLine::RemoveHolePipe(AecDbHvacDuct* pWPipe)
for (; it != end;)
{
if (!pXDatMap->GetNext(it, sKey, cVal)) break;
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
@@ -62,13 +62,13 @@ BOOL CDLGArribtEdit::OnInitDialog()
{
iIndex = m_wndLstAttrib.InsertItem(0, sKey);
if (cVal.nVt == VT_BSTR)
if (cVal.nVt == AecXData::kTypeString)
sKey.Format(_T("%s"), cVal.pszVal);
else if (cVal.nVt == VT_I4)
else if (cVal.nVt == AecXData::kTypeInt)
sKey.Format(_T("%d"), cVal.nVal);
else if (cVal.nVt == VT_R8)
else if (cVal.nVt == AecXData::kTypeDouble)
sKey.Format(_T("%g"), cVal.dVal[0]);
else if (cVal.nVt == (VT_BYREF | VT_R8))
else if (cVal.nVt == AecXData::kTypePoint)
sKey.Format(_T("%g,%g,%g"), cVal.dVal[0], cVal.dVal[1], cVal.dVal[2]);
m_wndLstAttrib.SetItemText(iIndex, 1, sKey);
@@ -203,13 +203,13 @@ void CDLGArribtEdit::OnOK()
sValue = m_wndLstAttrib.GetItemText(iPos, 1);
iVt = m_wndLstAttrib.GetItemData(iPos);
if (iVt == VT_BSTR)
if (iVt == AecXData::kTypeString)
m_pmapXData->SetAt(sKey, sValue);
else if (iVt == VT_I4)
else if (iVt == AecXData::kTypeInt)
m_pmapXData->SetAt(sKey, (int)_ttol(sValue));
else if (iVt == VT_R8)
else if (iVt == AecXData::kTypeDouble)
m_pmapXData->SetAt(sKey, _tcstod(sValue, NULL));
else if (iVt == (VT_BYREF | VT_R8))
else if (iVt == AecXData::kTypePoint)
{
pt.x = pt.y = pt.z = 0.0;
_stscanf(sValue, _T("%lf,%lf,%lf"), &(pt.x), &(pt.y), &(pt.z));
@@ -4334,7 +4334,7 @@ void TDbPipeLine::RemoveHolePipe(AecDbEwPipe* pWPipe)
for (; it != end;)
{
if (!pXDatMap->GetNext(it, sKey, cVal)) break;
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
@@ -312,15 +312,16 @@ void CFlangeDlg::SetAdoDb(CUIISQLiteServer *pDb)
void CFlangeDlg::GetEndF1(CString &sEndF)
{
//端面型式在 m_arFlangeVals 的下标 5(0公称直径 1法兰外径 2法兰高度 3法兰厚度 4法兰颈 5端面1 6端面2)
sEndF = _T("FF");
if (m_arFlangeVals.GetSize() > 0)
sEndF = m_arFlangeVals.GetAt(0);
if (m_arFlangeVals.GetSize() > 5 && !m_arFlangeVals.GetAt(5).IsEmpty())
sEndF = m_arFlangeVals.GetAt(5);
}
void CFlangeDlg::GetEndF2(CString &sEndF)
{
sEndF = _T("FF");
if (m_arFlangeVals.GetSize() > 1)
sEndF = m_arFlangeVals.GetAt(1);
if (m_arFlangeVals.GetSize() > 6 && !m_arFlangeVals.GetAt(6).IsEmpty())
sEndF = m_arFlangeVals.GetAt(6);
}
@@ -18033,6 +18033,103 @@ void DBL_AEC_DBEWFIT()
AecDbEwFitting* pEw = AecDbEwFitting::cast(pEnt);
if (pEw != NULL)
{
//法兰:双击弹出法兰对话框,把选中的法兰/垫片数据应用到该法兰对象
if (pEw->GetFittingType() == eFlange)
{
CString dbPath = FilePath::GetSysDir();
dbPath += _T("\\Plumbing.db");
CUIISQLiteServer * pADOServer = new CUIISQLiteServer;
if (!pADOServer->InitADOServer(dbPath))
{
AfxMessageBox(_T("数据库驱动加载数据库Plumbing.db失败!"));
delete pADOServer;
pEnt->close();
return;
}
//取当前法兰参数作为对话框初值
const AecDbObjXDataMap* pMap = pEw->GetSpecialtyData(AcDb::kForRead);
double dDN = 0.0;
pMap->GetAt(PIPE_DN, dDN);
double dPre = 1.0;
pMap->GetAt(PIPE_PRESSURE, dPre);
CString sODNo, sPro, sLevel;
pMap->GetAt(PIPE_ODSN, sODNo);
pMap->GetAt(DOC_PROJECT, sPro);
pMap->GetAt(PIPE_LEVEL, sLevel);
if (!sLevel.IsEmpty() && sPro.IsEmpty())
{
AecDbObjXDataMap xMap;
KTModelLayoutXData::ReadModelXData(KT_PIPEINIT, xMap);
xMap.GetAt(DOC_PROJECT, sPro);
}
{
CAcModuleResourceOverride rcTmp;
CFlangeDlg flgDlg;
flgDlg.SetAdoDb(pADOServer);
flgDlg.SetDN((int)dDN);
flgDlg.SetPressure(dPre);
flgDlg.SetLevel(sODNo, sPro, sLevel);
if (IDOK == flgDlg.DoModal())
{
//提取旧的接口
pEw->GetInterface(arOldInfs);
CStringArray arValuesF, arValuesG;
flgDlg.GetFlangeValues(arValuesF);
flgDlg.GetGasketValues(arValuesG);
//列: 0公称直径 1法兰外径 2法兰高度 3法兰厚度 4法兰颈 5端面
if (arValuesF.GetSize() >= 5)
{
double dWD = _ttof(arValuesF.GetAt(1)); //法兰盘外径
double dWh = _ttof(arValuesF.GetAt(3)); //法兰盘厚度
double dThk = _ttof(arValuesF.GetAt(3)); //法兰总厚
double dN = _ttof(arValuesF.GetAt(4)); //法兰颈
CString sEndF = _T("FF");
if (arValuesF.GetSize() > 5) sEndF = arValuesF.GetAt(5);
pEw->upgradeOpen();
AecDbObjXDataMap* pXDataMapSrc = pEw->GetSpecialtyData(AcDb::kForWrite);
pXDataMapSrc->SetAt(PIPE_WD, dWD);
pXDataMapSrc->SetAt(PIPE_WTHICK, dWh);
pXDataMapSrc->SetAt(PIPE_THICK, dThk);
pXDataMapSrc->SetAt(PIPE_N, dN);
pXDataMapSrc->SetAt(PIPE_FLANGF, sEndF);
if (arValuesG.GetSize() > 4)
{
pXDataMapSrc->SetAt(PIPE_GASKETM, arValuesG.GetAt(1));
pXDataMapSrc->SetAt(PIPE_PRESSURE, _ttof(arValuesG.GetAt(2)));
pXDataMapSrc->RemoveAt(PIPE_GASKET);
pXDataMapSrc->SetAt(PIPE_GASKET, _ttof(arValuesG.GetAt(3)));
pXDataMapSrc->SetAt(PIPE_GASKETDSC, arValuesG.GetAt(4));
}
pEw->ReCreateDraw2d();
pEw->ReCreateDraw3d();
pEw->downgradeOpen();
pEw->GetInterface(arNewInfs);
}
}
}
delete pADOServer;
}
else
{
WPipe::PipeParam* pParam = NULL;
pParam = pEw->GetPipeParam();
@@ -18094,6 +18191,7 @@ void DBL_AEC_DBEWFIT()
pEw->GetInterface(arNewInfs);
}
}
}
}
pEnt->close();
@@ -4082,7 +4082,7 @@ void TDbPipeLine::RemoveHolePipe(AecDbEwPipe* pWPipe)
for (; it != end;)
{
if (!pXDatMap->GetNext(it, sKey, cVal)) break;
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == VT_BSTR)//可能的实体句柄
if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄
{
AcDbHandle handle(cVal.pszVal);
+1 -1
View File
@@ -752,7 +752,7 @@ void CGJFCDlg::CreateChildItem(AecDbObjXDataMap* pXData)
for (; it != end; )
{
if (!pXData->GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_BSTR)
if (cVal.nVt == AecXData::kTypeString)
{
sHandle = cVal.pszVal;
}
+3 -3
View File
@@ -393,7 +393,7 @@ void CGJFCNewDlg::OnBnClickedButton10()
{
memset(&cVal,0,sizeof(AecXData));
if (!xData.GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_BSTR)
if (cVal.nVt == AecXData::kTypeString)
{
sHandle = cVal.pszVal;
}
@@ -456,7 +456,7 @@ void CGJFCNewDlg::OnBnClickedButton10()
{
memset(&cVal,0,sizeof(AecXData));
if (!xData.GetNext(it, sKey, cVal)) break;
if (cVal.nVt == VT_BSTR)
if (cVal.nVt == AecXData::kTypeString)
{
sHandle = cVal.pszVal;
}
@@ -984,7 +984,7 @@ void CGJFCNewDlg::CreateChildItem(AecDbObjXDataMap* pXData)
if (!pXData->GetNext(it, sKey, cVal))
break;
if (cVal.nVt == VT_BSTR)
if (cVal.nVt == AecXData::kTypeString)
{
sHandle = cVal.pszVal;
}
+56 -18
View File
@@ -7,6 +7,7 @@
#include <map>
#include "dbfiler.h"
#include "shJson.h"
#include <wtypes.h> // VARENUM / VT_* ,供 AecXData::EType 使用
#ifdef AECRXBASE_EXPORT
#define AECDLLIMPEXP __declspec(dllexport)
@@ -35,21 +36,29 @@
typedef std::pair<CString, CString> SH_BIM_REC;
typedef std::vector<SH_BIM_REC> SH_BIM_BLOCK;
typedef struct AecXData
// AecXData 会被其它模块(CoreLibrary / 各 Cmd)直接构造使用,必须随 AecRxBase 一起导出,
// 否则成员函数定义在 .cpp 里时其它模块会 LNK2019(unresolved external symbol)。
typedef struct AECDLLIMPEXP AecXData
{
/*
VT_I4 : int
VT_BSTR : psz
VT_R8 : double
VT_BYREF | VT_R8
VT_BYREF | VT_R8 + 1 pt
VT_BYREF | VT_R8 + 2
VT_BYREF | VT_R8 + 3 vect
VT_UI4 : id
VT_BYREF | VT_R8 + 4 : matrix3d
VT_BYREF | VT_R8 + 5 : binary data
// 数据类型标签(nVt)。直接用 wtypes.h 的 VARENUM(VT_*) 组合来表达,直观且与
// 原实现逐位一致;nVt 会写入 DWG/DXF/XData,改数值会破坏旧图兼容,务必保持不变。
enum EType
{
kTypeShort = VT_I2, // short
kTypeInt = VT_I4, // int
kTypeDouble = VT_R8, // double
kTypeString = VT_BSTR, // TCHAR* 字符串
kTypeSoftId = VT_UI4, // AcDbObjectId 软指针
kTypeInt64 = VT_I8, // 历史遗留(仅读)
kTypeHardId = VT_UI8, // AcDbObjectId 硬指针
kTypePoint = (VT_BYREF | VT_R8), // 点,不随实体变换
kTypePointWorld = (VT_BYREF | VT_R8) + 1, // 点,随实体变换
kTypeVector = (VT_BYREF | VT_R8) + 2, // 向量,不随实体变换
kTypeVectorWorld = (VT_BYREF | VT_R8) + 3, // 向量,随实体变换
kTypeMatrix = (VT_BYREF | VT_R8) + 4, // 矩阵(16个double,二进制块,128字节)
kTypeBinary = (VT_BYREF | VT_R8) + 5, // 二进制块
};
*/
int nVt;
LONG_PTR npszLen; //对应字符数据长度
@@ -61,23 +70,41 @@ typedef struct AecXData
TCHAR* pszVal; // 字符数据
void* pData; // binary data
};
// 1. 默认构造函数,替代原有代码中散落的 memset(&xdata, 0, sizeof(xdata));
// 实现见 AecDbObjXDataMap.cpp(随本 DLL 导出,其它模块可直接构造)。
AecXData();
// 2. 核心清理函数
void Free();
// 3. 深拷贝:先释放自身已持有的资源,再从 src 深拷贝。
// 字符串/矩阵/二进制会重新分配内存,不与 src 共享缓冲;
// 支持类型变化(nVt 不同也照常覆盖)。this == &src 时直接返回。
bool CopyFrom(const AecXData &src);
}AECXDATA;
class AECDLLIMPEXP AecDbObjXDataMap
{
private:
static const int g_nVersion;
public:
AecDbObjXDataMap();
AecDbObjXDataMap(const AecDbObjXDataMap& datamap);
virtual ~AecDbObjXDataMap();
// 把 kTypeMatrix 的 16 个 double 二进制块格式化为逗号分隔文本(供显示/比较使用)
static CString MatrixToString(const AecXData& xdata);
public:
BOOL SetAt(LPCTSTR pszKey,int nVal);
BOOL SetAt(LPCTSTR pszKey, DWORD dw);
BOOL SetAt(LPCTSTR pszKey, const int &nVal);
BOOL SetAt(LPCTSTR pszKey, const DWORD &dw);
BOOL SetAt(LPCTSTR pszKey, Adesk::Int16 nVal);
BOOL SetAt(LPCTSTR pszKey, const Adesk::Int16 &nVal);
BOOL SetAt(LPCTSTR pszKey,double dVal);
BOOL SetAt(LPCTSTR pszKey, const double &dVal);
BOOL SetAt(LPCTSTR pszKey,const AcGeDoubleArray& arVal);
BOOL SetAt(LPCTSTR pszKey,const AcGeVector3d& vt,BOOL bTransformBy = FALSE);
@@ -95,6 +122,11 @@ public:
BOOL SetAt(LPCTSTR pszKey,const AcGeMatrix3d& xform);
BOOL SetAt(LPCTSTR pszKey,void* pData,int nSize);
BOOL SetAt(LPCTSTR pszKey, const AecDbObjXDataMap& xDataMap);
BOOL GetAt(LPCTSTR pszKey, AecDbObjXDataMap& xDataMap);
BOOL GetAt(LPCTSTR pszKey,void*& pData,int& nSize) const;
BOOL GetAt(LPCTSTR pszKey,int& nVal) const;
@@ -189,7 +221,8 @@ public:
//prinf输出
void List() const;
void List(CListCtrl *pList, int nImage) const;
// 输出到字符串数组:每个元素占两项(先 key,后 value),供界面按两列展示。
void List(std::vector<CString> &pList) const;
int ComparedTo(const AecDbObjXDataMap* pXDataMap) const;
@@ -242,8 +275,13 @@ private:
void SecondAsKey(CString& sTemp,AecXData& xData);
// 把 xdata 以 pszKey 存入(已存在则覆盖)。接管 xdata 的所有权(内部把源置空)。
void SetXData(LPCTSTR pszKey, AecXData &xdata);
private:
mutable SHJson::WValue m_json;//临时,不序列化
std::map<CString,AecXData> m_xData;//序列化
};
#endif //_AecDbObjXDataMap_H__
+2 -1
View File
@@ -44,4 +44,5 @@ envi-code/
## 仓库
- 远端:`ssh://gjm@47.93.46.28:1216/srv/git/new-start.git`(origin,主分支 `main`)。
- 远端:`ssh://git@39.107.55.179:222/gjm/envi-code.git`(origin,主分支 `main`)。
- 访问方式:SSH 222 端口。各机器私钥不同,需在本机 `~/.ssh/config` 指定自己的私钥,**不要把私钥文件名提交到仓库**。
+2 -1
View File
@@ -30,5 +30,6 @@
## Git
- 远端 `origin`:`ssh://gjm@47.93.46.28:1216/srv/git/new-start.git`,主分支 `main`。
- 远端 `origin`:`ssh://git@39.107.55.179:222/gjm/envi-code.git`,主分支 `main`。
- 提交信息使用中文描述。
- SSH 走 222 端口;**各机器私钥不同**,在本机 `~/.ssh/config` 里指定即可,不要把私钥文件名写进仓库。