1005 lines
26 KiB
C++
1005 lines
26 KiB
C++
#include "stdafx.h"
|
||
#include <set>
|
||
#include <sstream>
|
||
#include <algorithm>
|
||
#include "UITools.h"
|
||
#include "MakeDim.h"
|
||
#include "AecDbEarthWorm.h"
|
||
#include "coreTools.h"
|
||
#include "FHBZSZDlg.h"
|
||
#include "aecdbObjXDataMap.h"
|
||
#include "JDZBDlg.h"
|
||
|
||
void SortPoints(AcGePoint3dArray& points, AcDbCurve* pLine);
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
namespace
|
||
{
|
||
#define XMAP_KEY _T("FIREDIM")
|
||
|
||
using namespace MK_DIM;
|
||
|
||
void split(LPCTSTR pszSrc, TCHAR sp, std::vector<CString> &vec)
|
||
{
|
||
if (!pszSrc) return;
|
||
|
||
vec.clear();
|
||
|
||
CString src(pszSrc);
|
||
|
||
CString oneString(_T(""));
|
||
TCHAR ch;
|
||
for (int i = 0; i < src.GetLength(); ++i)
|
||
{
|
||
ch = src[i];
|
||
if (ch == sp)
|
||
{
|
||
if (oneString.IsEmpty())
|
||
continue;
|
||
else
|
||
{
|
||
vec.push_back(oneString);
|
||
oneString.Empty();
|
||
}
|
||
}
|
||
else
|
||
oneString += ch;
|
||
}
|
||
if (!oneString.IsEmpty())
|
||
vec.push_back(oneString);
|
||
}
|
||
|
||
template <class T>
|
||
bool loadMkDimDll(T &proc, LPCSTR func, HINSTANCE &hmod)
|
||
{
|
||
if (!func) return false;
|
||
|
||
#ifndef ZWCAD
|
||
hmod = ::LoadLibrary(FilePath::GetArxDir() + _T("\\wfK.arx"));
|
||
#else
|
||
hmod = ::LoadLibrary(FilePath::GetArxDir() + _T("\\wfK.zrx"));
|
||
#endif
|
||
if (!hmod) return false;
|
||
|
||
proc = (T)::GetProcAddress(hmod, func);
|
||
if (!proc) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
bool hasSameStake(std::vector<NodeDim> &dims, LPCTSTR stake, NodeDim **pDim)
|
||
{
|
||
for (size_t i = 0; i < dims.size(); ++i)
|
||
{
|
||
if (dims[i].stake.CompareNoCase(stake) == 0)
|
||
{
|
||
*pDim = &dims[i];
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool beNeedDim(const EFnctType &type, bool includeFire)
|
||
{
|
||
if (!includeFire)
|
||
{
|
||
if (type == kFirwWall)
|
||
return false;
|
||
}
|
||
|
||
if ((type >= kDrainWell && type <= kHTOutLetHouse)
|
||
|| type == kProModel
|
||
|| type == kBDOutLetHouse )
|
||
//|| type == kSubEspJoint )
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
bool IsFamilyNode(const EFnctType &type)
|
||
{
|
||
return type == kProModel;
|
||
}
|
||
|
||
CString getFamilyNodeName(const EWFnctNode &node)
|
||
{
|
||
return node.szNodeSpec;
|
||
}
|
||
|
||
void analyFamilyNode(const EWFnctNode &node, NodeDim &dim)
|
||
{
|
||
//电力舱:通风口;逃生口|综合舱:通风口;人员出入口
|
||
std::vector<CString> vec(0), vTypes(0);
|
||
split(node.szNodeDefSpec, _T('|'), vec);
|
||
//split(_T("电力舱:通风口;逃生口;集水井|综合舱:通风口;逃生口;集水井"), _T('|'), vec);
|
||
if (vec.empty()) return;
|
||
int idx(-1);
|
||
CString str(_T(""));
|
||
CString room(_T("")), types(_T(""));
|
||
std::vector<NodeDim::ENodeType> etypes(0);
|
||
NodeDim::ENodeType ty(NodeDim::eNone);
|
||
for (size_t i = 0; i < vec.size(); ++i)
|
||
{
|
||
etypes.clear();
|
||
str = vec[i];
|
||
str.TrimRight();
|
||
idx = str.Find(_T(':'));
|
||
if (idx == -1) continue;
|
||
room = str.Left(idx);
|
||
types = str.Right(str.GetLength() - idx - 1);
|
||
split(types, _T(';'), vTypes);
|
||
if (vTypes.empty()) continue;
|
||
for (size_t t = 0; t < vTypes.size(); ++t)
|
||
{
|
||
if ((ty = getNodeType(vTypes[t])) != NodeDim::eNone)
|
||
etypes.push_back(ty);
|
||
}
|
||
|
||
if (dim.room_types.find(room) == dim.room_types.end())
|
||
dim.room_types.insert(std::make_pair(room, std::set<NodeDim::ENodeType>()));
|
||
dim.room_types[room].insert(etypes.begin(), etypes.end());
|
||
|
||
for (size_t t = 0; t < etypes.size(); t++)
|
||
{
|
||
NodeDim::ENodeType &type = etypes[t];
|
||
if (dim.type_rooms.find(type) == dim.type_rooms.end())
|
||
dim.type_rooms.insert(std::make_pair(type, std::set<CString>()));
|
||
dim.type_rooms[type].insert(room);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
void sortCenterPnt(AecDbEarthWorm *pEw, AcGePoint3dArray &arCenterPnts)
|
||
{
|
||
if (!pEw) return;
|
||
AcGePoint2d pt2dS(pEw->StartPoint()), pt2dE(pEw->EndPoint());
|
||
AcDbLine line(AcGePoint3d(pt2dS.x, pt2dS.y, 0.), AcGePoint3d(pt2dE.x, pt2dE.y, 0.));
|
||
SortPoints(arCenterPnts, &line);
|
||
}
|
||
|
||
// 通过 数组dims 内的索引 idx,得到其前面的对应舱室的防火墙个数,并拼成字符串
|
||
void getDimTextForFireWall(const int &idx, const std::vector<NodeDim> &dims, const NodeDim::ENodeType &type, std::vector<CString> &left, std::vector<CString> &right)
|
||
{
|
||
CString sLeft(_T("")), sRight(_T(""));
|
||
int num(0);
|
||
const NodeDim &curDim = dims[idx];
|
||
NodeDim::RoomTypes::const_iterator it = curDim.room_types.begin();
|
||
for (; it != curDim.room_types.end(); ++it)
|
||
{ // 向前搜索,寻找有type的此类舱室
|
||
sLeft.Empty();
|
||
sRight.Empty();
|
||
num = 0;
|
||
const CString &sRoom = it->first;
|
||
for (int i = 0; i < idx; ++i)
|
||
{
|
||
const NodeDim &dim = dims[i];
|
||
if (dim.room_types.find(sRoom) == dim.room_types.end()) continue;
|
||
if (dim.type_rooms.find(type) == dim.type_rooms.end()) continue;
|
||
++num;
|
||
}
|
||
sLeft.Format(_T("%s防火分区%d"), sRoom, num + 1);
|
||
sRight.Format(_T("%s防火分区%d"), sRoom, num + 2);
|
||
left.push_back(sLeft);
|
||
right.push_back(sRight);
|
||
}
|
||
}
|
||
|
||
void drawArrow(const AcGeVector3d &v
|
||
, const double &aW
|
||
, const AcGePoint3d &ptS
|
||
, AcDbObjectIdArray &ids)
|
||
{
|
||
AcDbObjectId id;
|
||
AcGePoint3d ptE;
|
||
double aL = aW * 100 / 33;
|
||
AcGeVector3d vt(v);
|
||
vt.normalize();
|
||
vt *= aL;
|
||
ptE = ptS + vt;
|
||
AcDbLine *p = new AcDbLine(ptS, ptE);
|
||
CoreTools::AddToModelSpace(p, NULL, true, &id);
|
||
ids.append(id);
|
||
vt *= -1;
|
||
double angle = atan(aW / (2 * aL));
|
||
vt.rotateBy(angle, AcGeVector3d::kZAxis);
|
||
p = new AcDbLine(ptE, ptE + vt);
|
||
CoreTools::AddToModelSpace(p, NULL, true, &id);
|
||
ids.append(id);
|
||
vt.rotateBy(2 * angle * -1, AcGeVector3d::kZAxis);
|
||
p = new AcDbLine(ptE, ptE + vt);
|
||
CoreTools::AddToModelSpace(p, NULL, true, &id);
|
||
ids.append(id);
|
||
}
|
||
|
||
double drawFireDimText(const AcGeVector3d &vtEw
|
||
, const AcGePoint3d &ptAlgn
|
||
, const double &h
|
||
, AcDbObjectId styleID
|
||
, std::vector<CString> &vLeft
|
||
, std::vector<CString> &vRight
|
||
, const bool bDraw
|
||
, AcDbObjectIdArray &ids)
|
||
{
|
||
CString left(_T("")), right(_T("")), room(_T(""));
|
||
|
||
for (size_t i = 0; i < vLeft.size(); ++i)
|
||
{
|
||
left += vLeft[i];
|
||
left += _T("、");
|
||
right += vRight[i];
|
||
right += _T("、");
|
||
}
|
||
left.TrimRight(_T("、"));
|
||
right.TrimRight(_T("、"));
|
||
|
||
AcGePoint3d ptLeft(ptAlgn), ptRight(ptAlgn);
|
||
AcGeVector3d vt1(vtEw), vt2(vtEw);
|
||
vt1.rotateBy(.5 * PI, AcGeVector3d::kZAxis);
|
||
vt1.normalize();
|
||
vt2.normalize();
|
||
vt1 *= h;
|
||
vt2 *= h;
|
||
ptLeft += vt1;
|
||
ptLeft -= vt2;
|
||
ptRight += vt1;
|
||
ptRight += vt2;
|
||
|
||
double angle = AcGeVector3d::kXAxis.angleTo(vtEw, AcGeVector3d::kZAxis);
|
||
// 此时文字为水平方向,取出长度
|
||
AcDbExtents ext, extAll;
|
||
AcDbText *pLeft = new AcDbText;
|
||
pLeft->setTextString(left);
|
||
pLeft->setTextStyle(styleID);
|
||
pLeft->setHeight(h);
|
||
pLeft->setHorizontalMode(AcDb::kTextRight);
|
||
pLeft->setAlignmentPoint(ptLeft);
|
||
|
||
AcDbText *pRight = (AcDbText*)pLeft->clone();
|
||
pRight->setTextString(right);
|
||
pRight->setHorizontalMode(AcDb::kTextLeft);
|
||
pRight->setPosition(ptRight);
|
||
|
||
pRight->getGeomExtents(ext);
|
||
extAll.addExt(ext);
|
||
|
||
pLeft->setRotation(angle);
|
||
pRight->setRotation(angle);
|
||
|
||
if (bDraw)
|
||
{
|
||
AcDbObjectId id;
|
||
CoreTools::AddToModelSpace(pLeft, NULL, true, &id);
|
||
ids.append(id);
|
||
CoreTools::AddToModelSpace(pRight, NULL, true, &id);
|
||
ids.append(id);
|
||
}
|
||
else
|
||
{
|
||
DELETE_PTR(pLeft);
|
||
DELETE_PTR(pRight);
|
||
}
|
||
double len = extAll.maxPoint().x - extAll.minPoint().x;
|
||
|
||
return len;
|
||
}
|
||
|
||
void drawFireDim(NodeDim &fd
|
||
, const int &idx
|
||
, const bool &bRight
|
||
, const double &w
|
||
, const double &h
|
||
, const double &aW
|
||
, const double &txtH
|
||
, AcDbObjectId &idStyle
|
||
, std::vector<CString> &vLeft
|
||
, std::vector<CString> &vRight
|
||
)
|
||
{
|
||
AcDbObjectId id;
|
||
AcDbObjectIdArray ids(0);
|
||
AcGePoint3d ptHs(AcGePoint3d::kOrigin), ptHe(AcGePoint3d::kOrigin)
|
||
, ptVs(AcGePoint3d::kOrigin), ptVe(AcGePoint3d::kOrigin)
|
||
, ptCross(AcGePoint3d::kOrigin);
|
||
|
||
AcGeVector3d vt(AcGeVector3d::kIdentity);
|
||
// 画竖线
|
||
NodeDim &dim = fd;
|
||
vt = dim.vt;
|
||
vt.rotateBy(.5 * PI * (bRight ? -1 : 1), AcGeVector3d::kZAxis);
|
||
vt.normalize();
|
||
vt *= h;
|
||
ptVs = dim.pntIns;
|
||
ptVe = ptVs + vt;
|
||
AcDbLine *p = new AcDbLine(ptVs, ptVe);
|
||
// 将竖线最后一个点(远离管廊)存入管廊的扩展数据内
|
||
// if (bRight)
|
||
// {
|
||
AecDbObjXDataMap xmap;
|
||
xmap.Read(fd.idEw, XMAP_KEY);
|
||
xmap.SetAt(fd.stake, ptVe);
|
||
xmap.Write(fd.idEw, XMAP_KEY);
|
||
// }
|
||
CoreTools::AddToModelSpace(p, NULL, true, &id);
|
||
ids.append(id);
|
||
// 画横线
|
||
vt.normalize();
|
||
vt *= h * .75;// +vLeft.size() * txtH;
|
||
ptCross = ptHs = ptHe = dim.pntIns;
|
||
ptCross += vt;
|
||
ptHs += vt;
|
||
ptHe += vt;
|
||
vt.normalize();
|
||
vt.rotateBy(.5 * PI, AcGeVector3d::kZAxis);
|
||
vt *= w * .5;
|
||
ptHs += vt;
|
||
ptHe -= vt;
|
||
p = new AcDbLine(ptHs, ptHe);
|
||
CoreTools::AddToModelSpace(p, NULL, true, &id);
|
||
ids.append(id);
|
||
// 画两个箭头
|
||
drawArrow(vt, aW, ptHs, ids);
|
||
drawArrow(-1 * vt, aW, ptHe, ids);
|
||
// 绘制文字
|
||
drawFireDimText(dim.vt, ptCross, txtH, idStyle, vLeft, vRight, true, ids);
|
||
CoreTools::generateGroup(NULL, ids);
|
||
}
|
||
|
||
template <class T1, class T2>
|
||
void _insert_(std::map<T1, std::set<T2>> &mm, const T1 &key, const T2 &value)
|
||
{
|
||
if (mm.find(key) == mm.end())
|
||
mm.insert(std::make_pair(key, std::set<T2>()));
|
||
mm[key].insert(value);
|
||
}
|
||
|
||
void mergeNode(const NodeDim &nd, NodeDim *pDim)
|
||
{
|
||
for (NodeDim::TypeRooms::const_iterator it = nd.type_rooms.begin(); it != nd.type_rooms.end(); ++it)
|
||
{
|
||
// 是否有相同的类型
|
||
NodeDim::TypeRooms::iterator preIt = pDim->type_rooms.find(it->first);
|
||
if (preIt == pDim->type_rooms.end())
|
||
{ // 不存在,直接插入
|
||
pDim->type_rooms.insert(*it);
|
||
}
|
||
else
|
||
{ // 存在,合并
|
||
preIt->second.insert(it->second.begin(), it->second.end());
|
||
}
|
||
}
|
||
|
||
for (NodeDim::RoomTypes::const_iterator it = nd.room_types.begin(); it != nd.room_types.end(); ++it)
|
||
{
|
||
// 是否有相同的舱室
|
||
NodeDim::RoomTypes::iterator preIt = pDim->room_types.find(it->first);
|
||
if (preIt == pDim->room_types.end())
|
||
{ // 不存在,直接插入
|
||
pDim->room_types.insert(*it);
|
||
}
|
||
else
|
||
{ // 存在,合并
|
||
preIt->second.insert(it->second.begin(), it->second.end());
|
||
}
|
||
}
|
||
}
|
||
|
||
AcGePoint3d getInsertPt(const AcGePoint3d &ptOrg, const EWFnctNode &node, const AcGeVector3d &v)
|
||
{
|
||
AcGePoint3d pt(ptOrg);
|
||
AcGeVector3d vt(v);
|
||
vt.normalize();
|
||
double delta(GLTools::getNodeOffset(node));
|
||
pt += vt * delta;
|
||
return pt;
|
||
}
|
||
|
||
void collectNodeInfoForDim(AcDbObjectId idEw
|
||
, std::vector<NodeDim> &nodeDims
|
||
, bool includeFire
|
||
, NodeDim *pNodeStart = NULL
|
||
, NodeDim *pNodeEnd = NULL)
|
||
{
|
||
AcDbObjectIdArray arrIDs;
|
||
GetConnectedWorms(idEw, arrIDs);
|
||
if (arrIDs.isEmpty()) return;
|
||
|
||
AcArray<ELongParam> arLongParam(0);
|
||
OPENOBJ_BEGIN(idEw, AcDb::kForRead, AecDbEarthWorm, pEw)
|
||
{
|
||
if (!pEw) return;
|
||
pEw->CalEarthWork(arLongParam);
|
||
}
|
||
OPENOBJ_END()
|
||
|
||
if (arLongParam.isEmpty()) return;
|
||
|
||
std::map<CString, double> guids;
|
||
for (int i = 0; i < arLongParam.length(); ++i)
|
||
guids.insert(std::make_pair(arLongParam[i].szIDlock, arLongParam[i].dDistStakeLen));
|
||
|
||
|
||
AcGePoint3dArray arCenPoints;
|
||
AcGeIntArray arEntTypes;
|
||
CUIntArray arColors;
|
||
AcArray<EWFnctNode> arNodes;
|
||
AcGePoint3dArray arNodePnts;
|
||
AcGePoint3d pt(AcGePoint3d::kOrigin);
|
||
CString nameNode(_T("")), nameRoom(_T(""));
|
||
NodeDim::ENodeType nodeType;
|
||
NodeDim nd;
|
||
double dAllLengthForEW(.0);
|
||
AcGePoint3d ptEwStart3d(AcGePoint3d::kOrigin);
|
||
AcGePoint2d ptEwStart2d(AcGePoint2d::kOrigin);
|
||
|
||
NodeDim nodS, nodE;
|
||
|
||
EWSEGMENT seg;
|
||
|
||
|
||
for (int i = 0; i < arrIDs.length(); ++i)
|
||
{
|
||
AcDbObjectId &id = arrIDs[i];
|
||
|
||
if (!i)
|
||
nodS.idEw = id;
|
||
if (i == arrIDs.length() - 1)
|
||
nodE.idEw = id;
|
||
|
||
arCenPoints.removeAll();
|
||
arEntTypes.removeAll();
|
||
arColors.RemoveAll();
|
||
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEarthWorm, pEw)
|
||
pEw->GetCenControlPoints(arCenPoints, arEntTypes, arColors, true);
|
||
|
||
sortCenterPnt(pEw, arCenPoints);
|
||
|
||
ptEwStart2d = pEw->StartPoint();
|
||
ptEwStart3d.x = ptEwStart2d.x;
|
||
ptEwStart3d.y = ptEwStart2d.y;
|
||
ptEwStart3d.z = pEw->StartElevation();
|
||
|
||
nd.vt = pEw->GetThisDir();
|
||
|
||
AcGePoint2d pt2d1(AcGePoint2d::kOrigin), pt2d2(AcGePoint2d::kOrigin);
|
||
// 遍历每个中心点,然后调用GetFncNodeAt函数,得到节点信息
|
||
for (int iPnt = 0; iPnt < arCenPoints.length(); ++iPnt)
|
||
{
|
||
nd.type_rooms.clear();
|
||
nd.room_types.clear();
|
||
arNodes.removeAll();
|
||
AcGePoint3d &ptC = arCenPoints[iPnt];
|
||
|
||
pEw->GetFncNodeAt(ptC, .5, arNodes, arNodePnts);
|
||
|
||
nd.idEw = pEw->objectId();
|
||
|
||
pt2d1.set(ptC.x, ptC.y);
|
||
//nd.distFromHead = dAllLengthForEW + pt2d1.distanceTo(ptEwStart2d);
|
||
nd.distFromHead = .0;
|
||
std::map<CString, double>::iterator it(guids.end());
|
||
for (int iNd = 0; iNd < arNodes.length(); ++iNd)
|
||
{
|
||
EWFnctNode &node = arNodes[iNd];
|
||
it = guids.find(node.szLockId);
|
||
if (it != guids.end())
|
||
nd.distFromHead = it->second;
|
||
|
||
if (!beNeedDim(node.eFnType, includeFire)) continue;
|
||
|
||
nd.pntIns = getInsertPt(ptC, node, nd.vt);
|
||
|
||
if (!i && !iPnt/* && node.eFnType == kStackNode*/)
|
||
{
|
||
nodS.pntIns = ptC;
|
||
nodS.stake = node.szStake;
|
||
nodS.vt = pEw->GetThisDir();
|
||
}
|
||
if (i == arrIDs.length() - 1 && iPnt == arCenPoints.length() - 1/* && node.eFnType == kStackNode*/)
|
||
{
|
||
nodE.pntIns = ptC;
|
||
nodE.stake = node.szStake;
|
||
nodE.vt = pEw->GetThisDir();
|
||
}
|
||
|
||
nd.stake = node.szStake;
|
||
|
||
|
||
nameRoom = pEw->GetRoomTypeByIdx(node.nRoomIndex);
|
||
if (IsFamilyNode(node.eFnType))
|
||
{
|
||
nameNode = getFamilyNodeName(node);
|
||
nd.name = nameNode;
|
||
analyFamilyNode(node, nd);
|
||
}
|
||
else
|
||
{
|
||
nodeType = getNodeType(node.eFnType);
|
||
nameNode = getNodeName(nodeType);
|
||
nd.name = nameNode;
|
||
// 填充type_rooms结构
|
||
_insert_<NodeDim::ENodeType, CString>(nd.type_rooms, nodeType, nameRoom);
|
||
|
||
// 填充room_types结构
|
||
_insert_<CString, NodeDim::ENodeType>(nd.room_types, nameRoom, nodeType);
|
||
}
|
||
|
||
}
|
||
|
||
// 在这里,对参通风口节点做特殊处理
|
||
// 由于 插入通风口时,可以同时插入防火土墙和另一个通风口,
|
||
// 所以在这里,对相同桩号进行融合
|
||
// 由于,桩号是排好序的,所以只需要和前一个桩号对比即可
|
||
NodeDim *preDim(NULL);
|
||
if (hasSameStake(nodeDims, nd.stake, &preDim))
|
||
mergeNode(nd, preDim);
|
||
else
|
||
nodeDims.push_back(nd);
|
||
}
|
||
pEw->GetSegment(0, seg);
|
||
dAllLengthForEW += seg.dDistLen;
|
||
OPENOBJ_END()
|
||
}
|
||
if (pNodeStart)
|
||
{
|
||
*pNodeStart = nodS;
|
||
pNodeStart->distFromHead = .0;
|
||
}
|
||
if (pNodeEnd)
|
||
{
|
||
*pNodeEnd = nodE;
|
||
pNodeEnd->distFromHead = dAllLengthForEW;
|
||
}
|
||
}
|
||
|
||
#define INS_TYPE(type)\
|
||
for (std::set<CString>::iterator it = room_##type.begin(); it != room_##type.end(); ++it)\
|
||
{\
|
||
_insert_<CString, NodeDim::ENodeType>(nodS.room_types, *it, NodeDim::##type);\
|
||
_insert_<NodeDim::ENodeType, CString>(nodS.type_rooms, NodeDim::##type, *it);\
|
||
_insert_<CString, NodeDim::ENodeType>(nodE.room_types, *it, NodeDim::##type);\
|
||
_insert_<NodeDim::ENodeType, CString>(nodE.type_rooms, NodeDim::##type, *it);\
|
||
}
|
||
|
||
#define GET_TYPES(type)\
|
||
itTR = nd.type_rooms.find(NodeDim::##type);\
|
||
if (itTR != nd.type_rooms.end())\
|
||
room_##type.insert(itTR->second.begin(), itTR->second.end())
|
||
|
||
void collectNodeInfoForStatistic(AcDbObjectId idEw, std::vector<NodeDim> &nodeDims, bool includeFire)
|
||
{
|
||
NodeDim nodS, nodE;
|
||
collectNodeInfoForDim(idEw, nodeDims, includeFire, &nodS, &nodE);
|
||
|
||
if (nodeDims.empty()) return;
|
||
|
||
// 如果舱室存在 防火墙 或 通风口 ,则在此舱室头尾加上相应的节点
|
||
std::set<CString> room_eFireWall;
|
||
std::set<CString> room_eVenDoghouse;
|
||
std::set<CString> room_eEscapeHatch;
|
||
std::set<CString> room_eDrainWell;
|
||
std::set<CString> room_eDoghouse;
|
||
std::set<CString> room_eOutlet;
|
||
for (size_t i = 0; i < nodeDims.size(); ++i)
|
||
{
|
||
NodeDim &nd = nodeDims[i];
|
||
NodeDim::TypeRooms::iterator itTR;
|
||
|
||
GET_TYPES(eFireWall);
|
||
GET_TYPES(eVenDoghouse);
|
||
GET_TYPES(eDrainWell);
|
||
GET_TYPES(eDoghouse);
|
||
GET_TYPES(eEscapeHatch);
|
||
GET_TYPES(eOutlet);
|
||
}
|
||
|
||
std::sort(nodeDims.begin(), nodeDims.end(), NodeDim::_com_by_dist());
|
||
|
||
if (EQUAL(nodeDims.begin()->distFromHead, nodS.distFromHead)) // 存在首节点
|
||
nodS = *nodeDims.begin();
|
||
if (EQUAL(nodeDims.rbegin()->distFromHead, nodE.distFromHead)) // 存在尾节点
|
||
nodE = *nodeDims.rbegin();
|
||
|
||
INS_TYPE(eFireWall);
|
||
INS_TYPE(eVenDoghouse);
|
||
INS_TYPE(eDrainWell);
|
||
INS_TYPE(eDoghouse);
|
||
INS_TYPE(eEscapeHatch);
|
||
INS_TYPE(eOutlet);
|
||
|
||
if (!EQUAL(nodeDims.begin()->distFromHead, nodS.distFromHead)) // 不存在首节点
|
||
nodeDims.insert(nodeDims.begin(), nodS);
|
||
else
|
||
*(nodeDims.begin()) = nodS;
|
||
|
||
if (!EQUAL(nodeDims.rbegin()->distFromHead, nodE.distFromHead)) // 不存在尾节点
|
||
nodeDims.push_back(nodE);
|
||
else
|
||
*(nodeDims.rbegin()) = nodE;
|
||
}
|
||
|
||
double getEwSectionWidth(AcDbObjectId id)
|
||
{
|
||
double w(.0);
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEarthWorm, pEw)
|
||
if (!pEw) return w;
|
||
AcGePoint2d pt = pEw->GetSize();
|
||
w = pt.x;
|
||
OPENOBJ_END()
|
||
return w;
|
||
}
|
||
|
||
CString mergeString(const NodeDim::RoomTypes &nds, LPCTSTR nodeName, LPCTSTR stake, const int *pIdx)
|
||
{
|
||
CString strFireWall = getNodeName(getNodeType(kFirwWall));
|
||
std::wstringstream ss;
|
||
std::wstring wstr;
|
||
ss << stake << _T(" ") << nodeName << _T(" ");
|
||
for (NodeDim::RoomTypes::const_iterator it = nds.begin(); it != nds.end(); ++it)
|
||
{
|
||
ss << (LPCTSTR)it->first << _T(":");
|
||
for (std::set<NodeDim::ENodeType>::const_iterator itType = it->second.begin(); itType != it->second.end(); ++itType)
|
||
{
|
||
if (*itType == NodeDim::eFireWall) continue;
|
||
ss << (LPCTSTR)*itType << _T("、");
|
||
}
|
||
wstr = ss.str().substr(0, ss.str().size() - 1);
|
||
ss.str(_T(""));
|
||
ss << wstr << _T(",");
|
||
}
|
||
wstr.clear();
|
||
wstr = ss.str().substr(0, ss.str().size() - 1);
|
||
if (pIdx)
|
||
{
|
||
std::wstringstream _ss;
|
||
_ss << *pIdx;
|
||
return CString(wstr.c_str()) + _ss.str().c_str();
|
||
}
|
||
return wstr.c_str();
|
||
}
|
||
|
||
CString mergeString(const NodeDim::TypeRooms &nds, LPCTSTR nodeName, LPCTSTR stake, const int *pIdx)
|
||
{
|
||
std::wstringstream ss;
|
||
std::wstring wstr;
|
||
ss << stake << _T(" ") << nodeName << _T(" ");
|
||
for (NodeDim::TypeRooms::const_iterator it = nds.begin(); it != nds.end(); ++it)
|
||
{
|
||
if (it->first == NodeDim::eFireWall) continue;
|
||
for (std::set<CString>::const_iterator itRoom = it->second.begin(); itRoom != it->second.end(); ++itRoom)
|
||
{
|
||
ss << (LPCTSTR)*itRoom << _T("、");
|
||
}
|
||
wstr = ss.str().substr(0, ss.str().size() - 1);
|
||
ss.str(_T(""));
|
||
ss << wstr;
|
||
ss << (LPCTSTR)getNodeName(it->first) << _T(",");
|
||
}
|
||
wstr.clear();
|
||
wstr = ss.str().substr(0, ss.str().size() - 1);
|
||
if (pIdx)
|
||
{
|
||
std::wstringstream _ss;
|
||
_ss << *pIdx;
|
||
return CString(wstr.c_str()) + _ss.str().c_str();
|
||
}
|
||
return wstr.c_str();
|
||
}
|
||
|
||
void drawNodeDimText(NodeDim &dim
|
||
, const double h
|
||
, const double len
|
||
, AcDbObjectId style
|
||
, bool bRight
|
||
, AcDbObjectIdArray &ids
|
||
, const int &idx
|
||
, const bool &byCenterLine) // 相同舱室、功能的节点序号
|
||
{
|
||
CString str(_T(""));
|
||
if (!byCenterLine)
|
||
{
|
||
CString strL = StakeTools::generateStakeString(dim.distFromHead, _T("L"));
|
||
str = mergeString(dim.type_rooms, dim.name, strL, &idx);
|
||
}
|
||
else
|
||
str = mergeString(dim.type_rooms, dim.name, dim.stake, &idx);
|
||
// 管廊宽
|
||
double w = getEwSectionWidth(dim.idEw);
|
||
|
||
AcGePoint3d ptIns = dim.pntIns;
|
||
AcGeVector3d vt = dim.vt;
|
||
|
||
// 转90
|
||
vt.rotateBy(.5 * PI * (bRight ? -1 : 1), AcGeVector3d::kZAxis);
|
||
vt.normalize();
|
||
vt *= .5 * w + len + h;
|
||
|
||
AcDbLine *pLine = new AcDbLine(ptIns, ptIns + vt);
|
||
|
||
vt.normalize();
|
||
vt *= .5 * w + len + 2*h;
|
||
ptIns += vt;
|
||
|
||
AcDbText *pTxt = new AcDbText();
|
||
pTxt->setTextString(str);
|
||
pTxt->setVerticalMode(AcDb::kTextVertMid);
|
||
if (bRight)
|
||
pTxt->setHorizontalMode(AcDb::kTextRight);
|
||
else
|
||
pTxt->setHorizontalMode(AcDb::kTextLeft);
|
||
pTxt->setTextStyle(style);
|
||
double angle = AcGeVector3d::kXAxis.angleTo(vt * (bRight ? -1 : 1), AcGeVector3d::kZAxis);
|
||
pTxt->setRotation(angle);
|
||
pTxt->setHeight(h);
|
||
|
||
AcDbObjectId id;
|
||
|
||
// 如果当前桩号上有防火墙标注
|
||
AecDbObjXDataMap xmap;
|
||
if (xmap.Read(dim.idEw, XMAP_KEY))
|
||
{
|
||
AcGePoint3d pt;
|
||
if (xmap.GetAt(dim.stake, pt))
|
||
{
|
||
DELETE_PTR(pLine);
|
||
vt.normalize();
|
||
vt *= h;
|
||
pt += vt;
|
||
ptIns = pt;
|
||
}
|
||
else
|
||
{
|
||
CoreTools::AddToModelSpace(pLine, NULL, true, &id);
|
||
ids.append(id);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
CoreTools::AddToModelSpace(pLine, NULL, true, &id);
|
||
ids.append(id);
|
||
}
|
||
|
||
|
||
pTxt->setAlignmentPoint(ptIns);
|
||
CoreTools::AddToModelSpace(pTxt, NULL, true, &id);
|
||
ids.append(id);
|
||
}
|
||
}
|
||
|
||
#define func_process(sfunc, ...)\
|
||
AcDbEntity *pEnt(NULL);\
|
||
func_##sfunc proc(NULL);\
|
||
HINSTANCE hmod(NULL);\
|
||
if (loadMkDimDll<func_##sfunc>(proc, #sfunc, hmod))\
|
||
{\
|
||
pEnt = proc(##__VA_ARGS__);\
|
||
::FreeLibrary(hmod);\
|
||
}\
|
||
return pEnt
|
||
|
||
namespace MK_DIM
|
||
{
|
||
|
||
NodeDim::ENodeType getNodeType(const EFnctType &type)
|
||
{
|
||
switch (type)
|
||
{
|
||
case kDrainWell:
|
||
return NodeDim::eDrainWell;
|
||
case kPipeDoghouse:
|
||
case kCableDoghouse:
|
||
case kHeatDoghouse:
|
||
return NodeDim::eDoghouse;
|
||
case kVenDoghouse:
|
||
return NodeDim::eVenDoghouse;
|
||
case kFirwWall:
|
||
return NodeDim::eFireWall;
|
||
case kEscapeHatch:
|
||
return NodeDim::eEscapeHatch;
|
||
case kSubEspJoint:
|
||
return NodeDim::eEspJoint;
|
||
case kFireOutlet:
|
||
case kEWOutLethouse:
|
||
case kHTOutLetHouse:
|
||
case kBDOutLetHouse:
|
||
return NodeDim::eOutlet;
|
||
default:
|
||
return NodeDim::eNone;
|
||
}
|
||
return NodeDim::eNone;
|
||
}
|
||
|
||
MK_DIM::NodeDim::ENodeType getNodeType(LPCTSTR psz)
|
||
{
|
||
CString str(psz);
|
||
|
||
if (str == _T("集水井"))
|
||
return NodeDim::eDrainWell;
|
||
else if (str == _T("投料口"))
|
||
return NodeDim::eDoghouse;
|
||
else if (str == _T("通风口"))
|
||
return NodeDim::eVenDoghouse;
|
||
else if (str == _T("防火墙"))
|
||
return NodeDim::eFireWall;
|
||
else if (str == _T("逃生口"))
|
||
return NodeDim::eEscapeHatch;
|
||
else if (str == _T("管线分支口"))
|
||
return NodeDim::eOutlet;
|
||
else if (str == _T("变形缝"))
|
||
return NodeDim::eEspJoint;
|
||
else
|
||
return NodeDim::eNone;
|
||
|
||
return NodeDim::eNone;
|
||
}
|
||
|
||
CString getNodeName(const NodeDim::ENodeType &type)
|
||
{
|
||
switch (type)
|
||
{
|
||
case NodeDim::eDrainWell:
|
||
return _T("集水井");
|
||
case NodeDim::eDoghouse:
|
||
return _T("投料口");
|
||
case NodeDim::eVenDoghouse:
|
||
return _T("通风口");
|
||
case NodeDim::eFireWall:
|
||
return _T("防火墙");
|
||
case NodeDim::eEscapeHatch:
|
||
return _T("逃生口");
|
||
case NodeDim::eOutlet:
|
||
return _T("管线分支口");
|
||
case NodeDim::eEspJoint:
|
||
return _T("变形缝");
|
||
default:
|
||
return _T("");
|
||
}
|
||
return _T("");
|
||
}
|
||
|
||
void collectNodeInfo_Dim(AcDbObjectId idEw, std::vector<NodeDim> &nodeDims, bool includeFire)
|
||
{
|
||
::collectNodeInfoForDim(idEw, nodeDims, includeFire);
|
||
}
|
||
|
||
void collectNodeInfo_Statistic(AcDbObjectId idEw, std::vector<NodeDim> &nodeDims, bool includeFire)
|
||
{
|
||
::collectNodeInfoForStatistic(idEw, nodeDims, includeFire);
|
||
}
|
||
}
|
||
|
||
namespace MK_DIM
|
||
{
|
||
|
||
void insertFireWallDim()
|
||
{
|
||
// 选择管廊
|
||
ads_point adsPnt;
|
||
ads_name adsName;
|
||
int nRes = acedEntSel(_T("\n请选择要标注的管廊。"), adsName, adsPnt);
|
||
if (nRes != RTNORM) return;
|
||
AcDbObjectId idEw(AcDbObjectId::kNull);
|
||
acdbGetObjectId(idEw, adsName);
|
||
if (!GLTools::isThisClass<AecDbEarthWorm>(idEw))
|
||
{
|
||
acutPrintf(_T("\n请选择一段管廊。"));
|
||
return;
|
||
}
|
||
|
||
// 绘制参数-------------------------------
|
||
// 标注 宽,高,箭头宽,字高,文字比例
|
||
double w(50), h(50), aW(2), txtH(1);
|
||
AcDbObjectId idStyle;
|
||
|
||
// 弹对话框
|
||
CAcModuleResourceOverride myResources;
|
||
CFHBZSZDlg dlg;
|
||
if (dlg.DoModal() != IDOK) return;
|
||
|
||
w = dlg.m_dW;
|
||
h = dlg.m_dH;
|
||
aW = dlg.m_dAW;
|
||
txtH = dlg.m_dTxtH;
|
||
idStyle = GLTools::getTextStyle(dlg.m_style);
|
||
if (!idStyle.isValid())
|
||
idStyle = GLTools::getTextStyle(_T("standard"));
|
||
|
||
// 收集参数-------------------------------
|
||
std::vector<NodeDim> nodeDims(0);
|
||
collectNodeInfo_Dim(idEw, nodeDims, true);
|
||
|
||
// 绘制
|
||
AcGePoint3d ptCross(AcGePoint3d::kOrigin), ptOldCross(AcGePoint3d::kOrigin);
|
||
double maxW(.0), oldMaxW(.0);
|
||
bool bRight(dlg.m_iSide == 0); // 是标在管廊方向右侧还是左侧
|
||
|
||
|
||
// 整理一下,把有防火墙的挑出来,之后再统一处理
|
||
std::vector<NodeDim> dims(0);
|
||
CString strName(_T(""));
|
||
for (size_t i = 0; i < nodeDims.size(); ++i)
|
||
{
|
||
NodeDim &dim = nodeDims[i];
|
||
NodeDim::TypeRooms::iterator it = dim.type_rooms.find(NodeDim::eFireWall);
|
||
if (it != dim.type_rooms.end())
|
||
dims.push_back(dim);
|
||
}
|
||
|
||
std::vector<CString> Left(0), Right(0);
|
||
for (size_t i = 0; i < dims.size(); ++i)
|
||
{
|
||
Left.clear();
|
||
Right.clear();
|
||
getDimTextForFireWall(i, dims, NodeDim::eFireWall, Left, Right);
|
||
NodeDim &dim = dims[i];
|
||
// 不是第一个
|
||
if (i)
|
||
{
|
||
AcDbObjectIdArray ids(0); // 临时,无用
|
||
NodeDim &pre_dim = dims[i - 1];
|
||
maxW = drawFireDimText(dim.vt, AcGePoint3d::kOrigin, txtH, idStyle, Left, Right, false, ids);
|
||
oldMaxW = drawFireDimText(pre_dim.vt, AcGePoint3d::kOrigin, txtH, idStyle, Left, Right, false, ids);
|
||
// if (dim.pntIns.distanceTo(pre_dim.pntIns) < __max(w, maxW + oldMaxW))
|
||
// bRight = !bRight;
|
||
}
|
||
drawFireDim(dim, i, bRight, w, h, aW, txtH, idStyle, Left, Right);
|
||
}
|
||
return;
|
||
}
|
||
|
||
void insertNodeDim()
|
||
{
|
||
// 选择管廊
|
||
ads_point adsPnt;
|
||
ads_name adsName;
|
||
int nRes = acedEntSel(_T("\n请选择要标注的管廊。"), adsName, adsPnt);
|
||
if (nRes != RTNORM) return;
|
||
AcDbObjectId idEw(AcDbObjectId::kNull);
|
||
acdbGetObjectId(idEw, adsName);
|
||
if (!GLTools::isThisClass<AecDbEarthWorm>(idEw))
|
||
{
|
||
acutPrintf(_T("\n请选择一段管廊。"));
|
||
return;
|
||
}
|
||
|
||
CAcModuleResourceOverride myResources;
|
||
CJDZBDlg dlg;
|
||
if (dlg.DoModal() != IDOK) return;
|
||
double txtH(dlg.m_textH);
|
||
double len(dlg.m_leaderL);
|
||
CString textStyle(dlg.m_style);
|
||
AcDbObjectId idStyle = GLTools::getTextStyle(textStyle);
|
||
if (!idStyle.isValid())
|
||
idStyle = GLTools::getTextStyle(_T("standard"));
|
||
|
||
// 收集参数-------------------------------
|
||
std::vector<NodeDim> nodeDims(0);
|
||
collectNodeInfo_Dim(idEw, nodeDims, false);
|
||
|
||
CString strFrieWall = getNodeName(getNodeType(kFirwWall));
|
||
CString strNodeName(_T("")), strOut(_T("")), _tmp(_T(""));
|
||
std::wstringstream ss;
|
||
std::wstring wstr;
|
||
AcDbObjectIdArray ids(0);
|
||
std::multiset<CString> mmapStrs;
|
||
typedef std::multiset<CString>::iterator mmapIt;
|
||
std::pair<mmapIt, mmapIt> pr;
|
||
size_t dif(0);
|
||
for (size_t i = 0; i < nodeDims.size(); ++i)
|
||
{
|
||
_tmp = mergeString(nodeDims[i].type_rooms, nodeDims[i].name, _T("0"), NULL);
|
||
mmapStrs.insert(_tmp);
|
||
pr = std::equal_range(mmapStrs.begin(), mmapStrs.end(), _tmp);
|
||
dif = std::distance(pr.first, pr.second);
|
||
drawNodeDimText(nodeDims[i], txtH, len, idStyle, dlg.m_iSide == 0, ids, dif, dlg.m_bByCenterLine ? true : false);
|
||
CoreTools::generateGroup(NULL, ids);
|
||
ids.removeAll();
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|