Files
envi-code/SourceCode/Code2026/CoreCommand/EarthWorm.cpp
T
company-desktop f8d10d5a3b perf: 增加截面 Region 缓存,开图恢复耗时降 56%
一次开图要做 5641 次截面恢复(22.4 s),其中大量内容重复,
而每次恢复都是"写临时 SAT 文件 + 从盘 acisIn + 删文件",单次 2.7~5.5 ms,
还要过一次杀软。本提交加一级母体缓存,命中直接 clone 返回。

新增 CoreLibrary/SectionRegionCache.{h,cpp},三个通道按 key 的正确性强度分开:
- kParam:纯参数 hash,用于 AecDbEwFitting::GetSection 的两个重载
  (key = dD/dt/HLR 标志 或 W/H/dt/HLR 标志,同参数必同几何)
- kAttr:类名 + spec XData(排除编号,并跳过 Id/点/向量/矩阵/二进制类型),
  只给 AecDbEwPipe 用。AecDbEwPipeBase 是很多类的基类,其余派生类实例间的
  区别就是截面,不满足"同数据必同截面",所以一律走内容 hash
- kText:SAT 文本内容 hash,用于 RegionAcisInDwgInFields 的其它类
  与 CoreTools::StringToRegion 的两个重载

约定:母体由缓存持有、永不外泄,Acquire/Put 都返回 clone,调用方拥有返回值;
母体不入库;每条通道 4096 条上限(AEC_SECTION_CACHE_MAX 可调),超出按 FIFO 淘汰;
AEC_SECTION_CACHE=0 可整体关闭做 A/B;卸载时 ClearAll() 释放,避免 DLL 析构顺序问题。

关键发现:SAT 文本第 2 行带存盘时间戳
  16 Autodesk AutoCAD 19 ASM 219.0.0.5600 NT 24 Thu Oct 22 10:19:20 2026
同一几何存盘时间不同,整份文本就不同(采样里两份 2596 字节的文本只差
10:19:20 与 10:19:16),这正是内容 hash 命中率只有 54% 的原因,与截面无关。
因此新增 HashSatText():算 hash 时跳过第 2 行,仅当该行含 "Autodesk" 时才跳过。
计数器也改用同一口径,避免两套统计互相矛盾。

实测(big1.dwg / AutoCAD 2020 / R230 Debug,AEC_SECTION_CACHE 关 vs 开):
  开图墙钟        108~113 s      -> 98 s
  截面恢复总耗时  22.4 s         -> 9.87 s(-56%)
    StringToRegion  14.05 s      -> 7.73 s
    RegionAcisIn     8.38 s      -> 2.14 s
  临时文件        6773 次/9.34MB -> 2875 次/3.61MB
  命中率          text 65.5% / attr 84.1% / param 88.8%
  clone 开销      命中 58us、未命中 73us(合计 0.37 s,可忽略)

顺带:
- tools/run_acad_perf.ps1 增加 -CacheOff 开关,用于同一构建上的 A/B 对比
- SectionPerfCounter 增加 AppendReport(),让缓存统计也写进同一份报告文件
- 诊断口子 AEC_SAT_SAMPLE=n 可导出未命中的 SAT 原文,用于定位这类差异

验证:R230 Debug 编译通过并部署;用脚本自动开图各跑一次(缓存关/开),
数据已写入 pipe-section-region-performance-plan.md。
尚未做:R190 编译(本机缺 v100 工具集)、Release 构建的收益复测、
开图期间 1140 次 RegionAcisout 回写(与本缓存无关,需单独立项)。
2026-10-28 20:41:05 +08:00

1237 lines
29 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StdAfx.h"
#include "StdArx.h"
#include "IniTools.h"
#include "resource.h"
#include "AecEwEditorReactor.h"
#include "EarThwormDef.h"
#include "KTCadUtility.h"
#include "KTInfoMonitor.h"
#include "CheckLock.h"
#include "SLTDlg.h"
#include "XMTJDlg.h"
#include "CCKSXDlg.h"
#include "uiiado.h"
#include "CoreTools.h"
#include <Iphlpapi.h>
#include "encryption.h"
#include "AecDbEwEquipment.h"
#include "AecDbCamera.h"
#include "AecDbPingFaDim.h"
#include "AecDbDimScaleZone.h"
#include "AecDbJoggedCamera.h"
#include "SectionPerfCounter.h"
#include "SectionRegionCache.h"
#include "breptools.h"
#include "HlrCutOption.h"
// 下面两个头文件不要删除,否则使用它们的工程会链接错误
#include "equinsdirjig.h"
#include "KTEntityDragMgr.h"
#include "AecUIContextMenu.h"
#pragma comment(lib, "IPHLPAPI.lib")
HINSTANCE _hdllInstance =NULL;
GlobalContext g_globalContext;
CCheckLock g_lockChk;
extern CXMTJDlg* g_wndProMain;
extern CCKSXDlg *g_wndListXData;
unsigned int g_lockState = 0;
#ifndef _ttof
#define _ttof(pszVal) _tcstod((pszVal), NULL)
#endif
#define g_pszLicenseFileName _T("licenseTime.dat")
#define g_pszMacDbFileName _T("cityStandard.db")
ACRX_DEFINE_MEMBERS(AcDbDoubleClickEdit);
void AddCommand(const TCHAR* cmdGroup, const TCHAR* cmdInt, const TCHAR* cmdLoc,
const int cmdFlags, const AcRxFunctionPtr cmdProc, const int idLocal = -1);
void InitApplication();
void UnloadApplication();
AC_IMPLEMENT_EXTENSION_MODULE(EarthWormDLL);
static bool g_bHasDog = TRUE;
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_hdllInstance = hInstance;
EarthWormDLL.AttachInstance(hInstance);
BrepTools::init();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
EarthWormDLL.DetachInstance();
}
return TRUE;
}
#pragma region encryption
typedef struct LicenseTime
{
int nYear;
int nMonth;
int nDay;
int nHour;
int nMinute;
}LICENSETIME;
void ReadLicenseTime(CTime& tStop)
{
TCHAR szfileName[MAX_PATH],szFullPath[MAX_PATH];
GetModuleFileName(_hdllInstance,szfileName,MAX_PATH);
TCHAR drive[_MAX_DRIVE] = _T(""),
dir[_MAX_DIR] = _T(""),
fname[_MAX_FNAME] = _T(""),
ext[_MAX_EXT] = _T("");
//e:\,program files\autodesk\,myarx,exe
_tsplitpath(szfileName, drive, dir, fname, ext);
_tcscpy(szFullPath, drive);
_tcscat(szFullPath, dir);
CString sFullPath = szFullPath;
sFullPath.TrimRight(_T('\\'));
//上一级目录
int nPos = sFullPath.ReverseFind(_T('\\'));
CString sPath = sFullPath.Mid(0,nPos + 1);
sFullPath = sPath + _T("sys\\");
sFullPath += g_pszLicenseFileName;
CFileFind find;
if (find.FindFile(sFullPath))
{
CFile file;
if (file.Open(sFullPath,CFile::modeRead))
{
char szHead[37];
//strcpy(szHead,"kingtouch license file 1.0");
file.Read((void*)szHead,sizeof(szHead));
UINT nSize = 1 // 加密信息(4位随机数+4位加密方法)
+ sizeof(LicenseTime);
byte* pData = new byte[nSize];
ASSERT(NULL != pData);
file.Read((void*)pData, nSize);
byte* pBuffer = pData + 1;
LicenseTime lt;
Adesk::UInt32 n;
switch (pData[0] & 0x0F)
{
case 0x0a: // 加密方法0x0a解密:将每个字节高低4位颠倒,然后和加密信息异或
{
for (n = 1; n < nSize; n++)
{
byte chLow = (pData[n] & 0x0F);
byte chHigh = (pData[n] & 0xF0);
byte chNew = ((chLow << 4) | (chHigh >> 4));
pData[n] = (chNew ^ pData[0]);
}
memcpy(&lt, pBuffer, sizeof(LicenseTime));
CTime tTmp(lt.nYear,lt.nMonth,lt.nDay,lt.nHour,lt.nMinute,0);
tStop = tTmp;
//acutPrintf(_T("\n%d %d %d %d %d"),lt.nYear,lt.nMonth,lt.nDay,lt.nHour,lt.nMinute);
}
default:
break;
}
file.Close();
}
}
}
#define ACBR_LIB( ver ) acbr## ver.dbx
#define STRINGIZE_WORKER( x ) _T(# x)
#define STRINGIZE( x ) STRINGIZE_WORKER(x)
CString getAcBrName(int ver)
{
CString ss;
ss.Format(_T("acbr%d.dbx"), ver);
return ss;
}
void GetMacAdr(CStringList& arMacs)
{
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
ULONG ulOutBufLen;
pAdapterInfo=(PIP_ADAPTER_INFO)malloc(sizeof(IP_ADAPTER_INFO));
ulOutBufLen = sizeof(IP_ADAPTER_INFO);
// 第一次调用GetAdapterInfo获取ulOutBufLen大小
if (::GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
{
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);
}
CString sText;
if ((dwRetVal = ::GetAdaptersInfo( pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
{
pAdapter = pAdapterInfo;
while (pAdapter)
{
sText = pAdapter->Description;
sText.MakeLower();
//acutPrintf(_T("\nName=%s"),sText);
if (sText.Find(_T("virtualbox")) == -1 &&
sText.Find(_T("vmware")) == -1)//不考虑虚拟机器
{
sText.Format(_T("%02x@%02x@%02x@%02x@%02x@%02x"),
pAdapter->Address[0],
pAdapter->Address[1],
pAdapter->Address[2],
pAdapter->Address[3],
pAdapter->Address[4],
pAdapter->Address[5]);
arMacs.AddTail(sText);
}
pAdapter = pAdapter->Next;
}
}
}
//禁止软件变为绿色版的!!!
int DbSetMacOrHasThis()
{
return 1395; //不限制
#ifdef BAL_REMOTE //集团版不检测绿色
return 1395;
#endif
#ifdef _DEBUG
return 1395;
#endif
TCHAR szfileName[MAX_PATH],szFullPath[MAX_PATH];
GetModuleFileName(_hdllInstance,szfileName,MAX_PATH);
TCHAR drive[_MAX_DRIVE] = _T(""),
dir[_MAX_DIR] = _T(""),
fname[_MAX_FNAME] = _T(""),
ext[_MAX_EXT] = _T("");
//e:\,program files\autodesk\,myarx,exe
_tsplitpath(szfileName, drive, dir, fname, ext);
_tcscpy(szFullPath, drive);
_tcscat(szFullPath, dir);
CString sFullPath = szFullPath;
sFullPath.TrimRight(_T('\\'));
//上一级目录
int nPos = sFullPath.ReverseFind(_T('\\'));
CString sPath = sFullPath.Mid(0,nPos + 1);
sFullPath = sPath + _T("sys\\");
sFullPath += g_pszMacDbFileName;
::CoInitialize(NULL);
CUIISQLiteServer sqldb;
if (!sqldb.InitADOServer(sFullPath))
{
return -1;
}
CStringList listMac;
GetMacAdr(listMac);
CString sSQL,sMac,sText;
sSQL = _T("select cptpos from aec_position");
CStringArray arVals;
sqldb.GetSelData(sSQL,arVals);
if (arVals.IsEmpty())
{
for (POSITION ps = listMac.GetHeadPosition();ps != NULL;)
{
sMac = listMac.GetNext(ps);
sSQL.Format(_T("insert into aec_position (cptpos) values ('%s')"),sMac);
if ( !sqldb.ExecuteSQL(sSQL) )
{
return -19;
}
}
return 1395;
}
else
{
for (int i = 0;i < arVals.GetSize();i++)
{
sText = arVals.GetAt(i);
if ( listMac.Find(sText) != NULL)
{
return 2396;
}
}
}
return 19;
}
#pragma endregion encryption
// ObjectARX EntryPoint
extern "C" AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
{
switch (msg)
{
case AcRx::kInitAppMsg:
{
#ifdef TRIAL_YEAR
{
CTime tCur = CTime::GetCurrentTime();
int year(tCur.GetYear());
if (year != TRIAL_YEAR)
{
CString str(_T(""));
str.Format(_T("%d试用版验证到期!"), TRIAL_YEAR);
AfxMessageBox(str);
return AcRx::kRetError;
}
}
#endif
//Comment out the following line if your
//application should be locked into memory
acrxDynamicLinker->unlockApplication(pkt);
acrxDynamicLinker->registerAppMDIAware(pkt);
acrxDynamicLinker->loadModule(getAcBrName(ARX), 1);
memset(&g_globalContext,0,sizeof(GlobalContext));
g_globalContext.g_nCirDeviation = 20;
g_globalContext.g_nEleGripPos = 1;
g_globalContext.g_lockPass = 0;
//判断数据库中是否初始化mac
int nDbSetMacOrHasThis = DbSetMacOrHasThis();
//if (!g_lockChk.CheckLock())
if (false)
{
CTime tStop(2026,5,1,2,2,2);
ReadLicenseTime(tStop);
CTime tCur = CTime::GetCurrentTime();
if (tCur < tStop)
{
if (nDbSetMacOrHasThis > 1394)
{
InitApplication();
}
g_globalContext.g_lockPass = 1394;
}
else
{
CString sTip;
sTip.LoadString(IDS_LOCK_CHKERROR);
acedAlert(sTip);
#ifdef ZWCAD
acrxDynamicLinker->unloadModule(_T("AecRxBase.zrx"));
#else
acrxDynamicLinker->unloadModule(_T("AecRxBase.arx"));
#endif
return AcRx::kRetError;
}
}
else
{
if (g_lockState)
{
CString msg;
CString path(FilePath::GetRootDir());
if (CoreTools::encryptionType() == 0)
{
msg = _T("\n 单机版授权未找到。是否运行“授权管理工具”?");
path += _T("\\上华软件-授权管理工具.exe");
}
else if (CoreTools::encryptionType() == 1)
{
msg = _T("\n 集团版授权未找到。是否运行“集团服务器设置工具”?");
path += _T("\\上华软件-集团服务器设置工具.exe");
}
else
{
AfxMessageBox(_T("检查授权失败!"));
return AcRx::kRetOK;
}
//#ifdef BAL_LOCAL
// msg = _T("\n 单机版授权未找到。是否运行“授权管理工具”?");
// path += _T("\\上华软件-授权管理工具.exe");
//#elif defined(BAL_REMOTE)
// msg = _T("\n 集团版授权未找到。是否运行“集团服务器设置工具”?");
// path += _T("\\上华软件-集团服务器设置工具.exe");
//#else
// AfxMessageBox(_T("无授权类型!"));
// return AcRx::kRetOK;
//#endif
if (path.IsEmpty()) return AcRx::kRetOK;
if (_taccess(path, 0x0) != 0x0)
{
AfxMessageBox(path + _T(" 文件未找到!\n 检查授权失败!"), MB_OK);
return AcRx::kRetOK;
}
int rel = AfxMessageBox(msg, MB_YESNO);
if (rel == IDNO) return AcRx::kRetOK;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (::CreateProcess(
path, // 应用程序名,可以为 NULL
NULL, // 命令行
NULL, // 进程安全属性
NULL, // 线程安全属性
FALSE, // 继承句柄
0, // 创建标志
NULL, // 环境变量
NULL, // 当前目录
&si, // 启动信息
&pi // 进程信息
))
{
// 等待进程结束
WaitForSingleObject(pi.hProcess, INFINITE);
// 清理句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
AfxMessageBox(_T("请重新启动CAD。"));
return AcRx::kRetOK;
}
}
if (nDbSetMacOrHasThis > 1394 && g_lockState == BIT_SUCCESS)
{
InitApplication();
}
else
{
AfxMessageBox(_T("检查授权失败!"));
}
g_globalContext.g_lockPass = 1394;
}
{
std::map<CString, CString> mm;
IniTools::getSectionContent(FilePath::GetSysDir() + _T("\\product.ini")
, _T("Product"), mm);
std::map<CString, CString>::const_iterator itName = mm.find(_T("CName"))
, itVer = mm.find(_T("Version"))
, itSubVer = mm.find(_T("SubVer"))
, itAppVer = mm.find(_T("APPVer"));
if (itName != mm.end() && itVer != mm.end() && itSubVer != mm.end())
{
CString s;
//s.Format(_T("%s %s (%s)"), itName->second, itVer->second, itSubVer->second);
s.Format(_T("%s %s %s"), itName->second, itVer->second, itAppVer->second);
acedGetAcadFrame()->SetWindowText(s);
}
}
#if ARX > 18
AecUIContext::AddContext(pkt);
#endif
}
break;
case AcRx::kLoadDwgMsg:
{
HlrCutOption::init();
break;
}
case AcRx::kUnloadAppMsg:
{
acrxDynamicLinker->unloadModule(getAcBrName(ARX));
g_lockChk.SendLogoutMessage();
g_BALock::instance().DrawEnd(true);
//int nDbSetMacOrHasThis = DbSetMacOrHasThis();
//if (g_globalContext.g_lockPass == 1394
// && nDbSetMacOrHasThis > 1394
// && g_lockState == BIT_SUCCESS)
// 验证是否成功,都应该自行注销
UnloadApplication();
SectionRegionCache::ClearAll();
//else
// return AcRx::kRetError;
#if ARX > 18
AecUIContext::DelContext();
#endif
}
break;
}
return AcRx::kRetOK;
}
AcArray<GripMessage> g_GripMessage;
bool DLLIMPEXP LastGripMessage(GripMessage &msg)
{
if (g_GripMessage.length() > 0)
{
msg = g_GripMessage.last();
return true;
}
return false;
}
bool DLLIMPEXP PickGripMessage(GripMessage& msg)
{
if (g_GripMessage.length() > 0)
{
msg = g_GripMessage.last();
g_GripMessage.removeLast();
return true;
}
return false;
}
void DLLIMPEXP PushGripMessage(GripMessage& msg)
{
//g_GripMessage.removeAll();
for (int i = 0;i < g_GripMessage.length();i++)
{
GripMessage& msgT = g_GripMessage.at(i);
if (!msgT.idHost.isValid())
{
g_GripMessage.removeAt(i);
i -= 1;
continue;
}
if (msgT.idHost == msg.idHost)
{
g_GripMessage.removeAt(i);
i -= 1;
continue;
}
}
g_GripMessage.append(msg);
}
DLLIMPEXP GlobalContext* GetGlobalContext()
{
return &g_globalContext;
}
AecEwEditorReactor* g_pEditorReactor(NULL);
AecNodeDoubleClickEdit* g_pDblEdit(NULL);
KTInfoMonitor *g_pInfoMonitor(NULL);
KTDocReactor *g_pDocReactor(NULL);
#define ADD_CMD(cmd, func) CoreTools::AddCommand(_T("KTEARTHWORMCORE"), _T(#cmd), _T(#cmd), ACRX_CMD_TRANSPARENT | ACRX_CMD_USEPICKSET, func)
#define ADD_CMD_EX(cmd, func, flag) CoreTools::AddCommand(_T("KTEARTHWORMCORE"), _T(#cmd), _T(#cmd), flag, func)
#ifndef NDEBUG
// Phase 0:截面恢复计数器。实现见 CoreLibrary/SectionPerfCounter.cpp
void envierpf_dump()
{
SectionPerf::Dump();
SectionRegionCache::Dump();
}
void envierpf_reset()
{
SectionPerf::Reset();
acutPrintf(_T("\n[SectionPerf] 已清零。"));
}
#endif
void InitApplication()
{
#ifdef ZWCAD
acrxLoadModule(ACRX_T("AecRxBase.zrx"), 1);
#else
acrxLoadModule(ACRX_T("AecRxBase.arx"),1);
#endif
g_globalContext.g_nCirDeviation = 4;
g_globalContext.g_nEleGripPos = 1;
g_globalContext.hWnd = NULL;
#pragma region rxinit
AcGeContext::gTol.setEqualPoint(1.e-6);
AcGeContext::gTol.setEqualVector(1.e-6);
AecDbBlackHoleEntity::rxInit();
CMFCDbDwgFiler::rxInit();
AecDbEarthWorm::rxInit();
AecDb3dRoadAxisLine::rxInit();
AecDbPortRoom::rxInit();
AecDbVenDoghouse::rxInit();
AecDbPipeDoghouse::rxInit();
AecDbCableDoghouse::rxInit();
AecDbEscapeHatchHouse::rxInit();
AecDbXXXDoghouse::rxInit();
AecDbEarthWormFitting::rxInit();
AecDbBuriedOutletDoghouse::rxInit();
AecDbProxyAcGiEntity::rxInit();
AecUnknownViewportDraw::rxInit();
AecUnknownViewportGeometry::rxInit();
AecDbEwPipeBase::rxInit();
AecDbEwPipe::rxInit();
AecDbShEarthWorm::rxInit();
AecDbEwFlexiblePipe::rxInit();
AecDbEwCable::rxInit();
AecDbEwFitting::rxInit();
AecDbEwEquipment::rxInit();
AecDbConnectDoghouse::rxInit();
AecDbEwPipeDim::rxInit();
AecDbSectionView::rxInit();
AecDbX3dPartEntity::rxInit();
AecDbBDPipeBase::rxInit();
AecDbMultiPartEntity::rxInit();
AecDbPipeHanger::rxInit();
//土建
AecDbXWall::rxInit();
AecDbXSlab::rxInit();
AecDbColumn::rxInit();
AecDbTongWall::rxInit();
AecDbBeam::rxInit();
AecDbFlume::rxInit();
AecDbSludgePipe::rxInit();
AecDbRiverGroove::rxInit();
AecDbGuardBar::rxInit();
AecDbBaseStair::rxInit();
AecDbLineStair::rxInit();
AecDbClimbStair::rxInit();
AecDbLineSegStair::rxInit();
AecDbArcStair::rxInit();
AecDbArcSegStair::rxInit();
AecDbZLineStair::rxInit();
AecDbMRPLineStair::rxInit();
AecDbParaLlelStair::rxInit();
AecDbCornerStair::rxInit();
AecDbAscent::rxInit();
AecDbDoubleMulStair::rxInit();
AecDbScissorsStair::rxInit();
AecDbCrossStair::rxInit();
AecDbTriangleStair::rxInit();
AecDbRectCornerStair::rxInit();
AecDbBalcony::rxInit();
AecDbPoolCell::rxInit();
AecDbXRoof::rxInit();
AecDbXOpening::rxInit();
AecDbGroupXOpening::rxInit();
AecDbZLineXOpening::rxInit();
AecDbGlassCurtainWall::rxInit();
AecDbParamEquipment::rxInit();
AecDbHolder::rxInit();
AecDbHanger::rxInit();
AecDbHvacDuct::rxInit();
AecDbHvacFitting::rxInit();
AecDbECableTray::rxInit();
AecDbEcFitting::rxInit();
AecDbBossHolder::rxInit();
AecInfCmdGrip::rxInit();
AecDbLandForm::rxInit();
AecDb3dRoad::rxInit();
AecDb3dRoadFitting::rxInit();
AecDbWeir::rxInit();
AecDbExtendedEntity::rxInit();
AecDbXEquipment::rxInit();
AecDbPathSectionSymbDim::rxInit();
AecDbXBG::rxInit();
AecDbXRoof::rxInit();
AecDbXDormerWindow::rxInit();
AecDbTerrain::rxInit();
AecDbAssembleWell::rxInit();
AecDbXStep::rxInit();
AecDbXApron::rxInit();
AcDbXFloorFrame::rxInit();
AecFloorViewDataRecord::rxInit();
AecDbDirPosition::rxInit();
AecDbXCamera::rxInit();
AecDbPingFaDim::rxInit();
AecDbDimScaleZone::rxInit();
AecDbInsulation::rxInit();
AecDbJoggedCamera::rxInit();
#pragma endregion
acrxBuildClassHierarchy();
acrxRegisterService(DBXEARTHWORM_MODULE);
g_pDblEdit = new AecNodeDoubleClickEdit;
AecDbPortRoom::desc()->addX(AcDbDoubleClickEdit::desc(),g_pDblEdit);
g_pEditorReactor = new AecEwEditorReactor;
acedEditor->addReactor(g_pEditorReactor);
//g_pDocReactor = new KTDocReactor();
//acDocManager->addReactor(g_pDocReactor);
//g_pDocReactor->init();
g_PictrueDlg::instance().Create(CSLTDlg::IDD);
g_PictrueDlg::instance().ShowWindow(SW_HIDE);
g_pInfoMonitor = new KTInfoMonitor;
g_pInfoMonitor->StartMonitor();
#pragma region command
//测试管廊
ADD_CMD(EW_CSGL, EW_CSGLCmdFnc);
//水平剖视
ADD_CMD(EW_SPPS, EW_SPPSCmdFnc);
//垂直剖视
ADD_CMD(EW_CZPS, EW_CZPSCmdFnc);
//1/4剖视 局部剖视
ADD_CMD(EW_ZJPS, EW_ZJPSCmdFnc);
//整体视图
ADD_CMD(EW_ZTST, EW_ZTSTCmdFnc);
//二维双线
ADD_CMD(EW_EWSX, EW_EWSXCmdFnc);
//纵断双线
ADD_CMD(EW_ZDSX, EW_ZDSXCmdFnc);
//二维单线
ADD_CMD(EW_EWDX, EW_EWDXCmdFnc);
//设置道路中心线
ADD_CMD(EW_SZDL, EW_SZDLCmdFnc);
//设置现状中心线
ADD_CMD(EW_XZDL, EW_XZDLCmdFnc);
//测试空间pline线
ADD_CMD(EW_3DPL, EW_3DPLCmdFnc);
//STL输出
ADD_CMD(EW_STLO, EW_STLOUTCmdFnc);
ADD_CMD(EW_SATO, EW_SALOUTCmdFnc);
ADD_CMD(EW_DWGO, EW_PDWGOUTCmdFnc);
ADD_CMD(EW_IGSO, EW_IGSOUTCmdFnc);
//ISO图: 按管线号导出 PCF 中间文件
ADD_CMD(EW_PCF, EW_PCFCmdFnc);
//ISO图: 自动分图(按管号/连通性/图幅把一个管道系统拆成多张 PCF)
ADD_CMD(EW_PCFSPLIT, EW_PCFSPLITCmdFnc);
//ISO图: PCF 转 ISO 图(DWG)
ADD_CMD(EW_PCFISO, EW_PCFISOCmdFnc);
//ISO图: PCF 按连通性分图(P3D 规则)
ADD_CMD(EW_PCFISOSPLIT, EW_PCFISOSPLITCmdFnc);
//管廊漫游
ADD_CMD(EW_GLMY, EW_GLMYCmdFnc);
ADD_CMD(EW_ENODE, EW_ENODECmdFnc);
ADD_CMD(EW_CTRLVIEW, EW_CTRLVIEWCmdFnc);
ADD_CMD(EW_SEGOFFSET, EW_SEGOFFSETCmdFnc);
//测试
ADD_CMD(CO_TEST, EW_CorTest);
ADD_CMD(CO_EXLAYER, CO_EXPORTLAYER);
// AecDbEwPipebase 实体镜像
ADD_CMD(CO_SHJX, CO_SHMirror);
//图形裁剪
ADD_CMD(CO_TXCJ, EW_TXCJCmd);
//图形切割
ADD_CMD(CO_TXQG, EW_TXQGCmd);
ADD_CMD(EW_TRNS, EW_SetTransparency);
ADD_CMD(CO_QSFX, EW_CO_QSFX);
//HVAC-TEST
ADD_CMD(HVAC_TEST, HVAC_TESTCmd);
ADD_CMD(HVAC_FTST, HVAC_FTSTCmd);
//ELC-CABLE-TEST
ADD_CMD(ELCB_TEST, ELCB_TESTCmd);
//剖切测试
ADD_CMD(PQ_TEST, PQ_TESTCmd);
//修改标准管廊标高和坡度
ADD_CMD(EW_MSEGE, EW_MSEGECmdFnc);
ADD_CMD(EW_MSEGG, EW_MSEGGCmdFnc);
//管廊连接
ADD_CMD(EW_GLRH, EW_GLRHCmdFnc);
//管廊桥接
ADD_CMD(EW_GLQJ, EW_GLQJCmdFnc);
//二维提图
ADD_CMD(EW_EWTT, EW_EWTTCmdFnc);
// 提图更新
ADD_CMD(EW_TTGX, EW_TTGXCmdFnc);
//三维提图
ADD_CMD(EW_SWTT, EW_SWTTCmdFnc);
//到奔特力
ADD_CMD(EW_DBTL, EW_DBTLCmdFnc);
//LOFTTEST
ADD_CMD(EW_LOFT, EW_LOFTCmdFnc);
//透明显示
ADD_CMD(EW_TMXS, EW_TMXSCmdFnc);
//视图提图
ADD_CMD(EW_STTT, EW_STTTCmdFnc);
//BIM特性表
ADD_CMD(EW_BIM, EW_BimInfoCmdFnc);
//结构视图
ADD_CMD(PL_JGST, PL_JGSTCmdFnc);
//工艺视图
ADD_CMD(PL_GYST, PL_GYSTCmdFnc);
//三维融合
ADD_CMD(PL_SWRH, PL_SWRHCmdFnc);
//墙体测试
ADD_CMD(PL_WALL, PL_WallCmdFnc);
//墙体复原->内部调用,墙体删除时,关联墙体融合复原
ADD_CMD(PL_QTFYT, PL_QTFYCmdFnc);
//暂除门墙的2d图元
ADD_CMD(PL_ZCMC, PL_ZCMCCmdFnc);
//门墙刷新
ADD_CMD(PL_MQSX, PL_MQSXCmdFnc);
//墙门刷新
ADD_CMD(PL_QMSX, PL_QMSXCmdFnc);
//平面平视
ADD_CMD(PL_PMPS, PL_PMPSCmdFnc);
//提取轮廓
ADD_CMD(PL_TQLK, PL_TQLKCmdFnc);
//提取边线
ADD_CMD(PL_TQBX, PL_TQBXCmdFnc);
//协同
//发送提资
ADD_CMD(CO_FSTZT, CO_FSTZCmdFnc);
//接收提资
ADD_CMD(CO_JSTZT, CO_JSTZCmdFnc);
//提资记录
ADD_CMD(CO_TZJLT, CO_TZJLCmdFnc);
//建数据库
ADD_CMD(CO_JSJKT, CO_JSJKCmdFnc);
//连接测试
ADD_CMD(CO_LJCST, CO_LJCSCmdFnc);
//协同
//账号登录
ADD_CMD(CO_ZHDLT, CO_ZHDLCmdFnc);
//设计上传
ADD_CMD(CO_SJSCT, CO_SCWJCmdFnc);
//下载文件
ADD_CMD(CO_SJXZT, CO_XZWJCmdFnc);
//项目图集
ADD_CMD(CO_XMTJT, CO_XMZLCmdFnc);
//图纸会议
ADD_CMD(CO_TZHYT, CO_TZHYCmdFnc);
//剖切窥视
ADD_CMD(CO_PQKST, CO_PQYCCmdFnc);
void DBL_AEC_BLACKHOLE();
ADD_CMD(DBL_AEC_BLACKHOLE, DBL_AEC_BLACKHOLE);
//开洞窥视
ADD_CMD(CO_KDKST, CO_KDKSCmdFnc);
//AecXXName
ADD_CMD(CO_AECXT, CO_AECXCmdFnc);
ADD_CMD(CO_DELPROXY, CO_DelProxyEntity);
//先启动
//CO_TZJLCmdFncEx();
// 查看产品类型
void co_product();
ADD_CMD(CO_PROD, co_product);
//查看 bitanswer 状态
ADD_CMD(CO_LOCK, CO_LockStatus);
//导出到db
ADD_CMD(CO_EXPORT, CO_EXPORT);
//提取AecDbBDPipebase实体几何信息到json
ADD_CMD(CO_JHXX, CO_JHXX);
//Read stl
ADD_CMD(CO_STLINT, SKPGRPReadStl);
//测试用,单提三维
ADD_CMD(CO_DTSW, CO_DTSWCmdFnc);
//代理检测
ADD_CMD(CO_DLJC, CO_DLJCCmdFnc);
//清理代理
ADD_CMD(CO_DLQC, CO_DLQCCmdFnc);
//Region测试
ADD_CMD(CO_RGCS, CO_RGCSCmdFnc);
//查看属性
ADD_CMD(CO_CKSX, CO_CKSXCmdFnc);
//集团授权借出
ADD_CMD(CO_CHECKOUT, CO_LockCheckout);
//集团授权还回
ADD_CMD(CO_CHECKTIN, CO_LockCheckin);
//提取原型
ADD_CMD(CO_TQYX, CO_TQYXCmdFnc);
//空命令
ADD_CMD(CO_EMPT, CO_EmptyCmd);
//SQLITE文件迁移
ADD_CMD(CO_SJQY, CO_SJQYCmd);
//MDB->DB
ADD_CMD(CO_MDB2DB, CO_MDB2DBCmd);
// 图块工具
ADD_CMD(CO_BLKTOL, CO_BlockTools);
//图纸比对
//ENTGET
ADD_CMD(ENTGET, CO_EntGet);
// 修改散线
ADD_CMD(DI_XGSX, CO_XGSX);
//为报表特殊增加的处理模板的命令
//组加实体
ADD_CMD(CO_ZJST, CO_ZJSTCmd);
//圆不可见
ADD_CMD(CO_YBKJ, CO_YBKJCmd);
// 清空实体的缓存
void co_clear_draw_buffer();
ADD_CMD(CO_QKHC, co_clear_draw_buffer);
//图块记录转90
ADD_CMD(CO_BLKRECZ, CO_BLKRECZ);
//图块记录删point
ADD_CMD(CO_BLKRESD, CO_BLKRESD);
//AcPolylineJig测试
ADD_CMD(CO_LXCS, CO_LXCSCmdFnc);
//测试AecDb3dRoadAxisLine
ADD_CMD(CO_DRAL, CO_DRALCmdFnc);
//测试SML脚本语言
ADD_CMD(SML, CO_SMLCmdFnc);
//句柄定位
ADD_CMD(JBDW, JBDWCmdFnc);
//审图会议
//...
//二三维图块,设备,部件.. 组装
//设备图库
ADD_CMD(SBTK, SBTKCmdFnc);
void co_cctv();
ADD_CMD(co_cctv, co_cctv);
void co_ccth();
ADD_CMD(co_ccth, co_ccth);
void co_bzfw();
ADD_CMD(co_bzfw, co_bzfw);
void DBL_AEC_DIMSCALEZONE();
ADD_CMD(DBL_AEC_DIMSCALEZONE, DBL_AEC_DIMSCALEZONE);
void DBL_AEC_XCAMERA();
ADD_CMD(DBL_AEC_XCAMERA, DBL_AEC_XCAMERA);
void DBL_AEC_JOGGEDCAMERA();
ADD_CMD(DBL_AEC_JOGGEDCAMERA, DBL_AEC_JOGGEDCAMERA);
void co_hlro();
ADD_CMD(co_hlro, co_hlro);
void co_resetHlrDraw3d();
ADD_CMD(co_resethlr, co_resetHlrDraw3d);
void co_cfix();
ADD_CMD(co_cfix, co_cfix);
void IsOneYearTrial();
ADD_CMD(co_isoneyeartrial, IsOneYearTrial);
//抽壳
void co_3dck();
ADD_CMD(co_3dck, co_3dck);
//bim输出
void co_bimout();
ADD_CMD(co_bimout, co_bimout);
//gltfout
void gltfout();
ADD_CMD(gltfout, gltfout);
void co_sublist();
ADD_CMD(co_sublist, co_sublist);
void AecJsonTest();
ADD_CMD(AecTest, AecJsonTest);
void AskAI();
ADD_CMD(co_chat, AskAI);
void SetAiCloud();
ADD_CMD(co_llm, SetAiCloud);
void co_copy();
ADD_CMD(co_copy, co_copy);
void co_align();
ADD_CMD(co_align, co_align);
void co_move();
ADD_CMD(co_move, co_move);
void co_setfxt();
ADD_CMD(co_sfxt, co_setfxt);
void _ui_context_command_helper_();
ADD_CMD_EX(_ui_context_command_helper_, _ui_context_command_helper_, ACRX_CMD_MODAL);
void co_qselect();
// 这里 不能用 ACRX_CMD_TRANSPARENT
// 否则 命令里面无法把实体加入到选择集,锁定文档也没有作用
// 除非做一个非模态对话框,在里面锁定文档,再操作。
ADD_CMD_EX(co_ksxz, co_qselect, ACRX_CMD_MODAL);
void co_qmodify();
ADD_CMD(co_ksxg, co_qmodify);
void co_sortUIContext();
ADD_CMD(co_yjcd, co_sortUIContext);
void joggedCamera();
ADD_CMD(co_zxpq, joggedCamera);
void pzjca();
ADD_CMD(co_pzjc, pzjca);
void pzjcs();
ADD_CMD(co_pzjcs, pzjcs);
#ifndef NDEBUG
// Phase 0:截面恢复计数器(仅 Debug,且需启动前设 AEC_PERF_COUNTER=1)
ADD_CMD(ENVIPERFDUMP, envierpf_dump);
ADD_CMD(ENVIPERFRESET, envierpf_reset);
#endif
#pragma endregion
if (CKTCadUtility::SetSystemVar(_T("STATUSBARAUTOWRAP"), 0))
acutPrintf(_T("\nSTATUSBARAUTOWRAP has been set to off."));
}
extern std::map<CString,PVOID> g_mapProMode2Fit;;
extern std::map<std::string,PVOID> g_mapProModeMD52Fit;
void UnloadApplication()
{
if (g_pDocReactor)
acDocManager->removeReactor(g_pDocReactor);
DELETE_PTR(g_pDocReactor);
//释放全部fit缓存
AecDbEarthWormFitting* pFit = NULL;
std::map<std::string,PVOID>::iterator it;
for (it = g_mapProModeMD52Fit.begin();it != g_mapProModeMD52Fit.end();it++)
{
pFit = (AecDbEarthWormFitting*)(*it).second;
DELETE_PTR(pFit);
}
g_mapProModeMD52Fit.clear();
g_mapProMode2Fit.clear();
deleteAcRxClass(AecDbJoggedCamera::desc());
deleteAcRxClass(AecDbInsulation::desc());
deleteAcRxClass(AecDbDimScaleZone::desc());
deleteAcRxClass(AecDbPingFaDim::desc());
deleteAcRxClass(AecDbXCamera::desc());
deleteAcRxClass(AecDbDirPosition::desc());
deleteAcRxClass(AecFloorViewDataRecord::desc());
deleteAcRxClass(AcDbXFloorFrame::desc());
deleteAcRxClass(AecDbXApron::desc());
deleteAcRxClass(AecDbXStep::desc());
deleteAcRxClass(AecDbAssembleWell::desc());
deleteAcRxClass(AecDbTerrain::desc());
deleteAcRxClass(AecDbXDormerWindow::desc());
deleteAcRxClass(AecDbXRoof::desc());
deleteAcRxClass(AecDbXBG::desc());
deleteAcRxClass(AecDbPathSectionSymbDim::desc());
deleteAcRxClass(AecDbXEquipment::desc());
deleteAcRxClass(AecDbExtendedEntity::desc());
deleteAcRxClass(AecDbWeir::desc());
deleteAcRxClass(AecDb3dRoadFitting::desc());
deleteAcRxClass(AecDb3dRoad::desc());
deleteAcRxClass(AecDbLandForm::desc());
deleteAcRxClass(AecInfCmdGrip::desc());
deleteAcRxClass(AecDbBossHolder::desc());
deleteAcRxClass(AecDbEcFitting::desc());
deleteAcRxClass(AecDbECableTray::desc());
deleteAcRxClass(AecDbHvacFitting::desc());
deleteAcRxClass(AecDbHvacDuct::desc());
deleteAcRxClass(AecDbHanger::desc());
deleteAcRxClass(AecDbHolder::desc());
deleteAcRxClass(AecDbParamEquipment::desc());
deleteAcRxClass(AecDbGlassCurtainWall::desc());
deleteAcRxClass(AecDbZLineXOpening::desc());
deleteAcRxClass(AecDbGroupXOpening::desc());
deleteAcRxClass(AecDbXOpening::desc());
deleteAcRxClass(AecDbXRoof::desc());
deleteAcRxClass(AecDbPoolCell::desc());
deleteAcRxClass(AecDbBalcony::desc());
deleteAcRxClass(AecDbRectCornerStair::desc());
deleteAcRxClass(AecDbTriangleStair::desc());
deleteAcRxClass(AecDbCrossStair::desc());
deleteAcRxClass(AecDbScissorsStair::desc());
deleteAcRxClass(AecDbDoubleMulStair::desc());
deleteAcRxClass(AecDbAscent::desc());
deleteAcRxClass(AecDbCornerStair::desc());
deleteAcRxClass(AecDbParaLlelStair::desc());
deleteAcRxClass(AecDbMRPLineStair::desc());
deleteAcRxClass(AecDbZLineStair::desc());
deleteAcRxClass(AecDbArcSegStair::desc());
deleteAcRxClass(AecDbArcStair::desc());
deleteAcRxClass(AecDbLineSegStair::desc());
deleteAcRxClass(AecDbClimbStair::desc());
deleteAcRxClass(AecDbLineStair::desc());
deleteAcRxClass(AecDbBaseStair::desc());
deleteAcRxClass(AecDbGuardBar::desc());
deleteAcRxClass(AecDbRiverGroove::desc());
deleteAcRxClass(AecDbSludgePipe::desc());
deleteAcRxClass(AecDbFlume::desc());
deleteAcRxClass(AecDbBeam::desc());
deleteAcRxClass(AecDbTongWall::desc());
deleteAcRxClass(AecDbColumn::desc());
deleteAcRxClass(AecDbXSlab::desc());
deleteAcRxClass(AecDbXWall::desc());
deleteAcRxClass(AecDbPipeHanger::desc());
deleteAcRxClass(AecDbMultiPartEntity::desc());
deleteAcRxClass(AecDbBDPipeBase::desc());
deleteAcRxClass(AecDbX3dPartEntity::desc());
deleteAcRxClass(AecDbSectionView::desc());
deleteAcRxClass(AecDbEwPipeDim::desc());
deleteAcRxClass(AecDbConnectDoghouse::desc());
deleteAcRxClass(AecDbEwEquipment::desc());
deleteAcRxClass(AecDbEwFitting::desc());
deleteAcRxClass(AecDbEwCable::desc());
deleteAcRxClass(AecDbEwFlexiblePipe::desc());
deleteAcRxClass(AecDbShEarthWorm::desc());
deleteAcRxClass(AecDbEwPipe::desc());
deleteAcRxClass(AecDbEwPipeBase::desc());
deleteAcRxClass(AecUnknownViewportGeometry::desc());
deleteAcRxClass(AecUnknownViewportDraw::desc());
deleteAcRxClass(AecDbProxyAcGiEntity::desc());
deleteAcRxClass(AecDbBuriedOutletDoghouse::desc());
deleteAcRxClass(AecDbEarthWormFitting::desc());
deleteAcRxClass(AecDbXXXDoghouse::desc());
deleteAcRxClass(AecDbEscapeHatchHouse::desc());
deleteAcRxClass(AecDbCableDoghouse::desc());
deleteAcRxClass(AecDbPipeDoghouse::desc());
deleteAcRxClass(AecDbVenDoghouse::desc());
deleteAcRxClass(AecDbPortRoom::desc());
deleteAcRxClass(AecDb3dRoadAxisLine::desc());
deleteAcRxClass(AecDbEarthWorm::desc());
deleteAcRxClass(CMFCDbDwgFiler::desc());
deleteAcRxClass(AecDbBlackHoleEntity::desc());
AecDbPortRoom::desc()->delX(AecNodeDoubleClickEdit::desc());
delete acrxServiceDictionary->remove(DBXEARTHWORM_MODULE);
//卸载反映器
acedEditor->removeReactor(g_pEditorReactor);
//删除反应器
if (g_pEditorReactor != NULL)
DELETE_PTR(g_pEditorReactor);
acedRegCmds->removeGroup(_T("KTEARTHWORMCORE"));
if (g_pInfoMonitor)
g_pInfoMonitor->StopMonitor();
DELETE_PTR(g_pDblEdit);
if (g_wndProMain != NULL)
delete g_wndProMain;
g_wndProMain = NULL;
if (g_wndListXData != NULL)
delete g_wndListXData;
g_wndListXData = NULL;
}