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

418 lines
11 KiB
C++

#include "stdafx.h"
#include "KTCADUtilityEx.h"
#include "AecDbEarthWorm.h"
#include "XFCTDlg.h"
#include <algorithm>
#include "coretools.h"
#define DEF_BLOCK_DWG _T("xfct.dwg")
namespace
{
void getFireEt(AecDbEarthWorm *pEw, std::vector<CXFCTDlg::_FIREET> &vec)
{
//FIREET:房间|安装方式|安装位置|X直径L|Y直径H|上间隙TSP|下间隙DSP|填充量|工作温度|性能|型号|名称|类别|厂家|偏移
if (!pEw) return;
CString sSrc(_T("")), sKey(_T("<FIREET:")), _temp(_T(""));
pEw->GetCrossSectionScr(sSrc);
// 得到2D管廊放样线
AcDbVoidPtrArray arPlines;
pEw->GetLoftingLines(arPlines);
if (sSrc.IsEmpty()) return;
CXFCTDlg::_FIREET fireet;
int idx1(-1), idx2(-1);
idx1 = sSrc.Find(sKey, 0);
idx2 = sSrc.Find(_T(">"), idx1 + sKey.GetLength());
std::vector<CString> data;
int type1(0), type2(0);
ERoom ro;
double w(.0);
while (idx1 != -1 && idx2 != -1)
{
_temp = sSrc.Mid(idx1 + sKey.GetLength(), idx2 - idx1);
CoreTools::SplitString(_temp, _T("|"), data);
if (data.size() < 15) continue;
fireet.room = _ttoi(data[0]);
fireet.dist = 10.;
if (fireet.room + 1 > arPlines.length()) continue;
AcGePoint3d pt1(AcGePoint3d::kOrigin), pt2(AcGePoint3d::kOrigin), pt3(AcGePoint3d::kOrigin);
((AcDbPolyline*)arPlines[fireet.room])->getStartPoint(pt1);
((AcDbPolyline*)arPlines[fireet.room])->getEndPoint(pt3);
((AcDbPolyline*)arPlines[fireet.room + 1])->getStartPoint(pt2);
w = pt1.distanceTo(pt2);
type1 = _ttoi(data[1]);
type2 = _ttoi(data[2]);
if (type1 == 0) // 中间
fireet.left = w * .5;
else
{
if (type2 == 0) // 左
fireet.left = 0;
else
fireet.left = w;
}
fireet.name = data[11];
fireet.path = FilePath::GetSysDir() + _T("\\") + DEF_BLOCK_DWG;
vec.push_back(fireet);
idx1 = sSrc.Find(sKey, idx2);
idx2 = sSrc.Find(_T(">"), idx1 + sKey.GetLength());
data.clear();
}
// 释放
for (int i = 0; i < arPlines.length(); ++i)
{
DELETE_PTR(arPlines[i]);
}
}
double getInsertPt(AecDbEarthWorm *pEw
, const double &dLast
, const CXFCTDlg::_FIREET &et
, AcDbObjectId blkID
, std::vector<AcGePoint3d> &pts)
{
if (!pEw) return 0;
// 得到2D管廊放样线
AcDbVoidPtrArray arPlines;
pEw->GetLoftingLines(arPlines);
if (et.room + 1 >= arPlines.length()) return 0;
// 舱室宽
AcGePoint3d pt1(AcGePoint3d::kOrigin), pt2(AcGePoint3d::kOrigin), pt3(AcGePoint3d::kOrigin);
((AcDbPolyline*)arPlines[et.room])->getStartPoint(pt1);
((AcDbPolyline*)arPlines[et.room])->getEndPoint(pt3);
((AcDbPolyline*)arPlines[et.room + 1])->getStartPoint(pt2);
double roomW = pt1.distanceTo(pt2);
// 图块大小
AcDbExtents ext;
AcDbBlockReference Ref;
Ref.setBlockTableRecord(blkID);
Ref.setScaleFactors(AcGeScale3d(.001, .001, .001));
Ref.getGeomExtents(ext);
double dY = (ext.maxPoint().y - ext.minPoint().y) * .5;
double dX = (ext.maxPoint().x - ext.minPoint().x) * .5;
// 管廊长度
double dLen = pEw->EndPoint().distanceTo(pEw->StartPoint());
// 管廊方向
AcGeVector2d vtDir(pEw->EndPoint() - pEw->StartPoint());
vtDir.normalize();
// 管廊垂直方向
AcGeVector2d vtV(vtDir);
vtV.rotateBy(-1 * PI * .5);
vtV.normalize();
// 灭火器距离廊壁距离
double dLeft(et.left);
// 防止灭火器与舱室墙壁碰撞
if (dLeft < dY) dLeft = dY;
if (dLeft > roomW - dY) dLeft = roomW - dY;
vtV *= dLeft;
AcGePoint2d ptS(pt1.x, pt1.y), ptE(pt3.x, pt3.y);
ptS += vtV;
// 从 ptS 开始,沿 vtDir 间隔 dSpace 布置
// 注意,不可以从0开始布置
AcGePoint2d _pt(AcGePoint2d::kOrigin);
double d = et.dist - dLast;
while (d <= dLen)
{
_pt = ptS + vtDir * d;
// 防止第一个和最后一个灭火器超过管廊起/终点
if (_pt.distanceTo(ptS) < dX)
_pt = ptS + vtDir * dX;
if (_pt.distanceTo(ptE) < dX)
_pt = ptE - vtDir * dX;
pts.push_back(AcGePoint3d(_pt.x, _pt.y, .0));
d += et.dist;
}
// 释放
for (int i = 0; i < arPlines.length(); ++i)
{
DELETE_PTR(arPlines[i]);
}
return dLen - (d - et.dist);
}
AcDbObjectId AddBlkFromDwg(LPCTSTR path)
{
if (!path) return AcDbObjectId::kNull;
CString sPath(path);
CString blkName = sPath.Right(sPath.GetLength() - sPath.ReverseFind(_T('\\')) - 1);
// 做图块
AcDbObjectId idRec;
AcDbBlockTable* pTbl = NULL;
acdbCurDwg()->getBlockTable(pTbl, AcDb::kForRead);
if (pTbl != NULL)
{
pTbl->getAt(blkName, idRec);
pTbl->close();
}
if (!idRec.isValid())
{
AcDbDatabase db(Adesk::kFalse);
if (Acad::eOk == db.readDwgFile(sPath))
{
acdbCurDwg()->insert(idRec, blkName, &db);
}
}
return idRec;
}
double insertFireEt(AecDbEarthWorm *pEw, const double &dLast, const CXFCTDlg::_FIREET &et)
{
if (!pEw) return false;
AcGeVector2d vt(pEw->EndPoint() - pEw->StartPoint());
AcGeVector3d vt3(vt.x, vt.y, 0.);
double angle = AcGeVector3d::kXAxis.angleTo(vt3, AcGeVector3d::kZAxis);
ERoom ro;
pEw->GetRoom(et.room, ro);
double roomW = ro.ptGe[0].distanceTo(ro.ptGe[1]);
AcDbObjectId idRec = AddBlkFromDwg(et.path);
if (!idRec.isValid())
{
acutPrintf(_T("\n插入图块失败。"));
return 0;
}
std::vector<AcGePoint3d> pts;
double d = getInsertPt(pEw, dLast, et, idRec, pts);
AcGePoint2d ptIns(AcGePoint2d::kOrigin);
double h(.0), v(.0);
for (int i = 0; i < pts.size(); ++i)
{
ptIns = AcGePoint2d(pts[i].x, pts[i].y);
AcDbBlockReference* pRef = new AcDbBlockReference;
pRef->setBlockTableRecord(idRec);
pRef->setScaleFactors(AcGeScale3d(.001, .001, .001)); // 图块中是毫米,转为米
pRef->setRotation(angle);
pRef->setPosition(AcGePoint3d(ptIns.x, ptIns.y, 0.));
CoreTools::AddToModelSpace(pRef);
}
return d;
}
}
void CXFCTDlg::Start()
{
CAcModuleResourceOverride myResources;
std::map<CString, int> ewTypes;
AcDbObjectId ewID(AcDbObjectId::kNull);
ads_name name;
ads_point adsPt;
int nRet = acedEntSel(_T("\n请选择布置好消防设备的管廊:"), name, adsPt);
if (nRet != RTNORM) return;
acdbGetObjectId(ewID, name);
CString src(_T(""));
std::vector<_FIREET> ets(0);
OPENOBJ_BEGIN(ewID, AcDb::kForRead, AecDbEarthWorm, pEw)
{
if (!pEw) return;
pEw->GetCrossSectionScr(src);
for (int i = 0; i < pEw->GetRoomCount(); ++i)
ewTypes.insert(std::make_pair(pEw->GetRoomTypeByIdx(i), i));
getFireEt(pEw, ets);
}
OPENOBJ_END()
AcDbObjectIdArray ids;
GetConnectedWorms(ewID, ids);
// 取出舱室信息
CXFCTDlg dlg(ewTypes, ets);
if (dlg.DoModal() != IDOK) return;
// 一段管廊需要画ets这么多的
ets = dlg.m_datas;
if (ets.empty()) return;
double dLast(.0);
for (int ie = 0; ie < ets.size(); ++ie)
{
dLast = ets.begin()->dist * (dlg.m_bByRad ? .5 : 1.);
_FIREET &et(ets[ie]);
for (int i = 0; i < ids.length(); ++i)
{
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, AecDbEarthWorm, pEw)
if (!pEw) continue;
dLast = insertFireEt(pEw, dLast, et);
OPENOBJ_END()
}
}
return;
}
IMPLEMENT_DYNAMIC(CXFCTDlg, CDialog)
CXFCTDlg::CXFCTDlg(const std::map<CString, int> &types, const std::vector<_FIREET> &data, CWnd* pParent /*=NULL*/)
: CDialog(CXFCTDlg::IDD, pParent)
, m_ewTypes(types)
, m_datas(data)
, m_bByRad(1)
{
m_pStrList = new CStringList();
std::map<CString, int>::iterator it(m_ewTypes.begin());
for (; it != m_ewTypes.end(); ++it)
{
m_pStrList->AddHead(it->first);
m_ewTypes2.insert(std::make_pair(it->second, it->first));
}
}
CXFCTDlg::~CXFCTDlg()
{
DELETE_PTR(m_pStrList);
}
void CXFCTDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, m_ctrlList);
DDX_Radio(pDX, IDC_RADIO1, m_bByRad);
}
BOOL CXFCTDlg::OnInitDialog()
{
CDialog::OnInitDialog();
initList(m_datas);
UpdateData(FALSE);
return TRUE;
}
BEGIN_MESSAGE_MAP(CXFCTDlg, CDialog)
ON_BN_CLICKED(IDOK, &CXFCTDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_BUTTON1, &CXFCTDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON4, &CXFCTDlg::OnBnClickedButton4)
ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CXFCTDlg::OnNMDblclkList1)
END_MESSAGE_MAP()
void CXFCTDlg::OnBnClickedOk()
{
UpdateData(TRUE);
m_datas.clear();
_FIREET fireet;
for (int i = 0; i < m_ctrlList.GetItemCount(); ++i)
{
fireet.name = m_ctrlList.GetItemText(i, 0);
std::map<CString, int>::iterator it = m_ewTypes.find(m_ctrlList.GetItemText(i, 1));
fireet.room = it != m_ewTypes.end() ? it->second : 0;
fireet.left = _ttof(m_ctrlList.GetItemText(i, 2));
fireet.dist = _ttof(m_ctrlList.GetItemText(i, 3));
fireet.path = m_ctrlList.GetItemText(i, 4);
m_datas.push_back(fireet);
}
CDialog::OnOK();
}
void CXFCTDlg::initList(const std::vector<_FIREET> &ets)
{
m_ctrlList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_SINGLEROW);
m_ctrlList.InsertColumn(0, _T("灭火器名称"), LVCFMT_LEFT, 100);
m_ctrlList.InsertColumn(1, _T("所属舱室"), LVCFMT_LEFT, 100);
m_ctrlList.InsertColumn(2, _T("距舱室左侧距离(米)"), LVCFMT_LEFT, 140);
m_ctrlList.InsertColumn(3, _T("两个灭火器间距(米)"), LVCFMT_LEFT, 140);
m_ctrlList.InsertColumn(4, _T("出图图案(双击可编辑)"), LVCFMT_LEFT, 255);
m_ctrlList.SetColumnItemData(0, NULL, ET_Edit);
m_ctrlList.SetColumnItemData(1, NULL, ET_Combo);
m_ctrlList.SetColumnItemData(2, NULL, ET_Edit);
m_ctrlList.SetColumnItemData(3, NULL, ET_Edit);
// 排个序
std::vector<_FIREET> ar(ets);
std::sort(ar.begin(), ar.end());
int prec(1);
int idx(0);
for (size_t i = 0; i < ar.size(); ++i)
{
const _FIREET &et(ar[i]);
idx = m_ctrlList.InsertItem(m_ctrlList.GetItemCount(), et.name);
m_ctrlList.SetColumnItemData(1, m_pStrList, ET_Combo);
m_ctrlList.SetItemText(idx, 1, m_ewTypes2[et.room]);
m_ctrlList.SetItemText(idx, 2, TypeConvert::f2s(et.left, &prec));
m_ctrlList.SetItemText(idx, 3, TypeConvert::f2s(et.dist, &prec));
m_ctrlList.SetItemText(idx, 4, et.path);
}
}
// 添加
void CXFCTDlg::OnBnClickedButton1()
{
int idx = m_ctrlList.InsertItem(m_ctrlList.GetItemCount(), _T("灭火器"));
m_ctrlList.SetColumnItemData(1, m_pStrList, ET_Combo);
m_ctrlList.SetItemText(idx, 1, m_pStrList->GetHead());
m_ctrlList.SetItemText(idx, 2, _T("0"));
m_ctrlList.SetItemText(idx, 3, _T("10"));
m_ctrlList.SetItemText(idx, 4, FilePath::GetSysDir() + _T("\\") + DEF_BLOCK_DWG);
}
// 删除
void CXFCTDlg::OnBnClickedButton4()
{
int idx = m_ctrlList.GetSelectionMark();
if (idx == -1)
{
AfxMessageBox(_T("请选择一行记录!"));
return;
}
m_ctrlList.DeleteItem(idx);
}
void CXFCTDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
if (pNMItemActivate->iItem == -1) return;
if (pNMItemActivate->iSubItem != 4) return;
// str 是一个dwg文件路径
CString str = m_ctrlList.GetItemText(pNMItemActivate->iItem, pNMItemActivate->iSubItem);
if (str.IsEmpty() || _taccess(str, 0x00) != 0x00) str = _T("");
CString szFilter = _T("dwg文件 (*.dwg)||");
CFileDialog fileDlg(FALSE, _T("dwg"), str, OFN_HIDEREADONLY, szFilter, acedGetAcadFrame());
if (fileDlg.DoModal() != IDOK) return;
m_ctrlList.SetItemText(pNMItemActivate->iItem, pNMItemActivate->iSubItem, fileDlg.GetPathName());
*pResult = 0;
}