#include "stdafx.h" #include "KTCADUtilityEx.h" #include "AecDbEarthWorm.h" #include "XFCTDlg.h" #include #include "coretools.h" #define DEF_BLOCK_DWG _T("xfct.dwg") namespace { void getFireEt(AecDbEarthWorm *pEw, std::vector &vec) { //FIREET:房间|安装方式|安装位置|X直径L|Y直径H|上间隙TSP|下间隙DSP|填充量|工作温度|性能|型号|名称|类别|厂家|偏移 if (!pEw) return; CString sSrc(_T("")), sKey(_T("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 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 &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 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 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 &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::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::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(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; }