418 lines
11 KiB
C++
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;
|
|
}
|