Files
envi-code/SourceCode/Code2026/EarthWormCmd/ZDOutput.cpp
T
2026-09-28 15:28:50 +08:00

2038 lines
55 KiB
C++

#include "StdAfx.h"
#include <algorithm>
#include <sstream>
#include <iterator>
#include "UITools.h"
#include "ZDOutput.h"
#include "KTCadUtility.h"
#include "KTCadUtilityEx.h"
#include "KTSetting.h"
#include "aecdbObjXDataMap.h"
#include "KTModelLayoutXData.h"
#include "MakeDim.h"
#include "sorttab.h"
#include "dimfactory.h"
namespace
{
#define TEXT_STYLE _T("Pipe_Dim")
#define STAKE_SECTION _T("DIM_DATA")
#define STAKE_SEGMENT _T("szStake")
#define STAKE_TYPE _T("szNodeSpec")
#define STAKE_FNTYPE _T("eFnType")
#define NODE_TYPE _T("szNodeSpec")
#define NODE_ID _T("szLockId")
#define NODE_NAME _T("szNodeName")
#define ZDTB_FILE _T("\\zdtbsz.dat")
#define STAKE_FILE_NAME _T("\\stakedata.dat")
// 标尺与网格最左侧间距
static double g_rule_grid_space = 2;
// 内容块需要平移的矩阵
static AcGeMatrix3d g_content_blk_mat;
// 最后一张图宽度范围
static std::pair<double, double> g_prRang;
}
namespace
{
bool AddToTableRecord(AcDbEntity* pEnt, AcDbObjectId &id, bool bClose = true, AcDbObjectId *pEntID = NULL)
{
if (!pEnt) return false;
AcDbObjectId entID;
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbBlockTableRecord, pRec)
if (!pRec) return false;
pRec->appendAcDbEntity(entID, pEnt);
if (bClose) pEnt->close();
OPENOBJ_END()
if (pEntID)
*pEntID = entID;
return true;
}
double getScale(LPCTSTR s)
{
if (!s) return .0;
AecDbObjXDataMap xDataMap;
KTModelLayoutXData::ReadModelXData(_T("EW_EARTHWORMINIT"), xDataMap);
CString scale(_T("1:100"));
xDataMap.GetAt(s, scale);
int idx = scale.Find(_T(":"));
CString a = scale.Left(idx);
CString b = scale.Mid(idx+1);
//return _ttof(b)/_ttof(a);
return 1;
}
bool InBox(const AcGePoint3d &pt, const double maxX, const double &minX)
{
return ( pt.x <= maxX && pt.x >= minX );
}
void drawCircle(AcDbObjectId id, const AcGePoint3d &pt, const double &r = 10)
{
AcDbCircle *p = new AcDbCircle(pt, AcGeVector3d::kZAxis, r);
AddToTableRecord(p, id);
}
struct EWNodeDimInfo
{
CString strType;
CString strID;
CString strStake;
CString strName;
int fnType;
AcDbExtents ext;
AcGePoint3d getInsPnt() const
{
AcGePoint3d ptIns(AcGePoint3d::kOrigin);
Midpoint((ext.maxPoint()), (ext.minPoint()), ptIns);
return ptIns;
}
struct _com_by_x
{
bool operator () (EWNodeDimInfo &a, EWNodeDimInfo &b)
{
return a.getInsPnt().x < b.getInsPnt().x;
}
};
};
typedef std::map<CString, EWNodeDimInfo> EWNodeDimInfos;
void catalogNodeType(const std::vector<AcDbObjectId> &ids, EWNodeDimInfos &nds)
{
AecDbObjXDataMap xmap;
CString strType(_T("")), strID(_T("")), strStake(_T("")), strName(_T(""));
int fnType;
AcDbObjectId id;
EWNodeDimInfo info;
double dist(.0);
for (size_t i = 0; i < ids.size(); ++i)
{
id = ids[i];
xmap.Empty();
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbEntity, pEnt)
if (!xmap.Read(pEnt, STAKE_SECTION)) continue;
if (!xmap.GetAt(NODE_TYPE, strType)) continue;
if (!xmap.GetAt(NODE_ID, strID)) continue;
if (!xmap.GetAt(STAKE_FNTYPE, fnType)) continue;
if (xmap.GetAt(STAKE_SEGMENT, strStake)) // 非必须
info.strStake = strStake;
xmap.GetAt(NODE_NAME, strName);
// 里程节点不需要标注
if (fnType == kStackNode) continue;
// 变形缝不需要标注
if (fnType == kEspJoint) continue;
// 子变形缝需要看一下配置
if (fnType == kSubEspJoint)
{
bool bDimJoin = TypeConvert::s2i(ZD_OUT::getConfiguration(ZD_OUT::KEY_BXFBZ_S)) == 0 ? false : true;
if (!bDimJoin) continue;
}
info.strID = strID;
info.fnType = fnType;
info.strType = strType;
info.strName = strName;
EWNodeDimInfos::iterator it = nds.find(strID);
AcDbExtents ext;
pEnt->getGeomExtents(ext);
if (it == nds.end())// 未找到,新建
{
info.ext = ext;
nds.insert(std::make_pair(strID, info));
}
else
it->second.ext.addExt(ext);
OPENOBJ_END()
}
}
}
namespace
{
std::vector<std::pair<CString, CString>> g_config;
// 生成默认的配置数据
int initConfig()
{
for (size_t i = 0; i < sizeof(ZD_OUT::g_TableHead) / sizeof(LPCTSTR); i++)
g_config.push_back(std::make_pair(ZD_OUT::g_TableHead[i], _T("1")));
// 纵断计算数据 文字设置
g_config.push_back(std::make_pair(ZD_OUT::KEY_HEAD_H, _T("2")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_HEAD_S, _T("Pipe_Dim")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_HEAD_W, _T("0.75")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_DATA_H, _T("1.5")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_DATA_S, _T("Pipe_Dim")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_DATA_W, _T("0.5")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_DATA_GL_STAKENO, _T("K0+000")));
// 网格设置
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_INTERVAL, _T("1")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_PREC, _T("1")));
// 网格设置 文字设置
g_config.push_back(std::make_pair(ZD_OUT::KEY_RATIO_H , _T("0.5")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_RATIO_S , _T("Pipe_Dim")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_RATIO_W , _T("0.5")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_H , _T("0.5")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_S , _T("Pipe_Dim")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_W , _T("0.5")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_ARROW_W , _T("0.25")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_WH, _T("0.25")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_GRID_TEXT_INTERVAL, _T("0.75")));
// 节点设置
g_config.push_back(std::make_pair(ZD_OUT::KEY_NODE_SCALE, _T("1.0")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_BXFBZ_S, _T("1")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_NODE_DIMTYPE, _T("1")));
// 引出标注设置
g_config.push_back(std::make_pair(ZD_OUT::KEY_YCBZ_H , _T("1.75")));
g_config.push_back(std::make_pair(ZD_OUT::KEY_YCBZ_S , _T("Pipe_Dim")));
// 其它设置
g_config.push_back(std::make_pair(ZD_OUT::KEY_QTSZ_LCJG , _T("200")));
return 1;
}
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);
}
void analyGradeAndDistance(LPCTSTR psz, CString &sGrade, CString &sDistance, CString &start, CString &end)
{
// 坡度%/距离(起始号-结束号)
if (!psz) return;
CString str(psz);
// idx1 '/' 位置
int idx1 = str.FindOneOf(_T("/"));
if (idx1 == -1) return;
sGrade = str.Left(idx1);
// idx2 '(' 位置
int idx2 = str.Find(_T("("), idx1);
if (idx2 == -1) return;
sDistance = str.Mid(idx1 + 1, idx2 - idx1 - 1);
// idx3 '-'位置
int idx3 = str.Find(_T("-"), idx2);
if (idx3 == -1) return;
start = str.Mid(idx2 + 1, idx3 - idx2 - 1);
// idx4 ')'位置
int idx4 = str.Find(_T(")"), idx3);
if (idx4 == -1) return;
end = str.Mid(idx3 + 1, idx4 - idx3 - 1);
return;
}
bool readConfiguration()
{
CString sPath = FilePath::getProgramDataFolder() + ZDTB_FILE;
if (_taccess(sPath, 0x0) != 0x0) return false;
CStdioFile file(sPath, CFile::shareDenyRead);
if (!file.m_hFile) return false;
CString line(_T(""));
std::vector<CString> vec(0);
std::pair<CString, CString> pr;
std::vector<std::pair<CString, CString>> _temp(0);
while (file.ReadString(line))
{
split(line, _T('='), vec);
if (vec.size() != 2) continue;
pr.first = vec[0];
pr.second = vec[1];
_temp.push_back(pr);
}
int countOfHead = sizeof(ZD_OUT::g_TableHead) / sizeof(LPCTSTR);
// 前countOfHead个为纵断数据顺序,所以要与文件中一至
if (_temp.size() < countOfHead) return false;
std::vector<std::pair<CString, CString>>::iterator it_temp = _temp.begin()
, it_config = g_config.begin();
std::advance(it_temp, countOfHead);
std::advance(it_config, countOfHead);
// 将 g_config 尾部备份
std::vector<std::pair<CString, CString>> xx(it_config, g_config.end());
// 取文件中前 countOfHead 的数据给g_config,此时,g_config会变成countOfHead个
g_config.assign(_temp.begin(), it_temp);
// 把尾部备份还原
g_config.insert(g_config.end(), xx.begin(), xx.end());
// 把尾部的数据与文件中的一一对应
for (size_t i = countOfHead; i < g_config.size(); ++i)
{
for (size_t j = 0; j < _temp.size(); ++j)
{
if (_temp[j].first == g_config[i].first)
{
g_config[i].second = _temp[j].second;
}
}
}
return true;
}
static int g_init = initConfig();
CString getConfiguration(LPCTSTR key)
{
if (!key) return _T("");
std::vector<std::pair<CString, CString>>::iterator it = g_config.begin();
for (; it != g_config.end(); ++it)
{
if (it->first.CompareNoCase(key) == 0)
return it->second;
}
return _T("");
}
CString getScaleS2()
{
// 读出纵断比例
AecDbObjXDataMap xDataMap;
xDataMap.SetAt(_T("S2"), _T("1:100"));
KTModelLayoutXData::ReadModelXData(_T("EW_EARTHWORMINIT"), xDataMap);
CString str(_T("1:100"));
xDataMap.GetAt(_T("S2"), str);
return str;
}
void scalePaperSpace(AcDbObjectId paperID , AcDbObjectIdArray &arIDs)
{
if (!GLTools::isThisClass<AcDbBlockTableRecord>(paperID)) return;
if (arIDs.isEmpty()) return;
// 读出纵断比例
CString str(getScaleS2());
std::vector<CString> vecs(0);
split(str, _T(':'), vecs);
if (vecs.size() != 2) return;
double Yscale = _ttoi(vecs[1]) / _ttoi(vecs[0]);
// end
// 首先新建一个块表
AcDbObjectId bkID(AcDbObjectId::kNull);
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
if (!pDb) return;
AcDbBlockTable *pTbl(NULL);
Acad::ErrorStatus es = pDb->getBlockTable(pTbl, AcDb::kForWrite);
if (es != Acad::eOk) return;
AcDbBlockTableRecord *pRc = new AcDbBlockTableRecord;
pRc->setName(_T("*xx"));
if (pTbl->add(pRc) != Acad::eOk)
{
pTbl->close();
return;
}
bkID = pRc->objectId();
pTbl->close();
// end
// 将所有 arIDs 内的实本,都clone出一份,加入到新的块表内,然后删除。
AcDbExtents ext, extAll;
AcDbObjectIdArray arrTemp(arIDs);
for (int i = 0; i < arrTemp.length(); ++i)
{
OPENOBJ_BEGIN(arrTemp[i], AcDb::kForWrite, AcDbEntity, pEnt)
if (!pEnt) continue;
if (!AcDbCurve::cast(pEnt)) continue;
pEnt->getGeomExtents(ext);
extAll.addExt(ext);
if (pRc->appendAcDbEntity((AcDbCurve*)pEnt->clone()) == Acad::eOk)
{
arIDs.removeAt(i);
pEnt->erase();
}
OPENOBJ_END()
}
pRc->close();
// end
// 新建一个 块参照 按比例进行缩放后炸碎,将炸出的实体入到到 paper 中。
AcDbVoidPtrArray arrPtr;
AcGePoint3d ptIns(extAll.minPoint());
AcDbBlockReference *pRef = new AcDbBlockReference(ptIns, bkID);
AcGeScale3d scale;
scale.set(1., Yscale, 1.);
pRef->setScaleFactors(scale);
es = pRef->explode(arrPtr);
OPENOBJ_BEGIN(paperID, AcDb::kForWrite, AcDbBlockTableRecord, pPaper)
for (size_t i = 0; i < arrPtr.length(); i++)
{
AcDbEntity *p = (AcDbEntity*)arrPtr[i];
if (pPaper->appendAcDbEntity(p) == Acad::eOk)
arIDs.append(p->objectId());
}
OPENOBJ_END()
//pRef->close();
DELETE_PTR(pRef);
// end
// 最后删除 新建的 块表
OPENOBJ_BEGIN(bkID, AcDb::kForWrite, AcDbBlockTableRecord, pRec)
if (pRec) pRec->erase();
OPENOBJ_END()
// pRc->erase();
// pRc->close();
// end
}
void ADSProjectSendToBottom(AcDbObjectId &idPaper, AcDbObjectIdArray &ids)
{
Acad::ErrorStatus es;
OPENOBJ_BEGIN(idPaper, AcDb::kForRead, AcDbBlockTableRecord, pBlock)
if (!pBlock) return;
AcDbSortentsTable *pSortTbl(NULL);
if (Acad::eOk == pBlock->getSortentsTable(pSortTbl, AcDb::kForWrite, true))
{
es = pSortTbl->moveToBottom(ids);//moveToTop
pSortTbl->close();
}
OPENOBJ_END()
acDocManager->sendStringToExecute ( acDocManager->curDocument(), _T("_regen\n"), false, true );
}
}
namespace
{
struct _compare_pt_y { bool operator () (AcGePoint3d pt1, AcGePoint3d pt2) const { return pt1.y < pt2.y; } };
// bWeitght 粗线在左,细线在右
void insertSegmentOfRuleline(AcDbObjectId &id, const AcGePoint3d &ptS, const AcGePoint3d &ptE, bool bWeight)
{
double w(TypeConvert::s2f(getConfiguration(ZD_OUT::KEY_GRID_WH)));
AcGeVector3d vtl(AcGeVector3d::kXAxis * w);
AcGeVector2d vtp(AcGeVector2d::kXAxis * w * .25f);
AcDbLine *pLine = new AcDbLine(bWeight ? ptS : ptS - vtl, bWeight ? ptE : ptE - vtl);
AcDbPolyline *pPLine = new AcDbPolyline();
AcGePoint2d pt2S(ptS.x, ptS.y), pt2E(ptE.x, ptE.y);
pPLine->addVertexAt(0, bWeight ? pt2S - 3*vtp : pt2S - vtp, 0, w*.5, w*.5);
pPLine->addVertexAt(1, bWeight ? pt2E - 3*vtp : pt2E - vtp, 0, w*.5, w*.5);
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_RULE);
g_LayerMgr::instance().setLayer(pPLine, GLTools::gLayer_ZD_RULE);
AddToTableRecord(pLine, id);
AddToTableRecord(pPLine, id);
}
void insertRulelineText(
AcDbObjectId &id
, const AcGePoint3d &pt
, LPCTSTR pszText
, int clr
, const float &textH
, const float &textWFactor
, LPCTSTR pszTextStyle )
{
float fIntervalWithRule(TypeConvert::s2f(getConfiguration(ZD_OUT::KEY_GRID_TEXT_INTERVAL)));
AcDbText *pText = new AcDbText();
pText->setHeight(textH);
pText->setWidthFactor(textWFactor);
pText->setHorizontalMode(AcDb::kTextRight);
pText->setTextString(pszText);
AcGeVector3d vtX(AcGeVector3d::kXAxis * (fIntervalWithRule));
AcGeVector3d vtY(AcGeVector3d::kYAxis * textH * .5);
pText->setAlignmentPoint(pt - vtX - vtY);
AcDbObjectId idTextStyle = GLTools::getTextStyle(TEXT_STYLE);
if (!idTextStyle.isNull())
pText->setTextStyle(idTextStyle);
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_ZD_TEXT_RULE);
AddToTableRecord(pText, id);
}
// 画比例尺
void drawScaleRule(
AcDbObjectId recID
, AcGePoint3d pt
, LPCTSTR pszH
, LPCTSTR pszV
, const double &arW
, const double &textH
, const double &textWF
, LPCTSTR textStyle )
{
AcDbExtents extH, extV;
AcDbObjectId idTextStyle = GLTools::getTextStyle(textStyle);
double deltaXH(.0), deltaYH(.0);
double deltaXV(.0), deltaYV(.0);
double lenghtH(.0), lenghtV(.0);
//////////////////////////////////////////////////////////////////////////
AcDbText *pTextH = new AcDbText();
pTextH->setHeight(textH);
pTextH->setWidthFactor(textWF);
pTextH->setHorizontalMode(AcDb::kTextMid);
pTextH->setTextString(pszH);
if (!idTextStyle.isNull()) pTextH->setTextStyle(idTextStyle);
pTextH->getGeomExtents(extH);
deltaXH = extH.maxPoint().x - extH.minPoint().x;
deltaYH = extH.maxPoint().y - extH.minPoint().y;
lenghtH = deltaXH * 2.5;
//////////////////////////////////////////////////////////////////////////
AcDbText *pTextV = new AcDbText();
pTextV->setHeight(textH);
pTextV->setWidthFactor(textWF);
pTextV->setRotation(PI * .5);
pTextV->setVerticalMode(AcDb::kTextVertMid);
pTextV->setTextString(pszV);
if (!idTextStyle.isNull()) pTextV->setTextStyle(idTextStyle);
pTextV->getGeomExtents(extV);
deltaXV = extV.maxPoint().x - extV.minPoint().x;
deltaYV = extV.maxPoint().y - extV.minPoint().y;
lenghtV = deltaYV * 2.5;
//////////////////////////////////////////////////////////////////////////
AcGePoint3d ptIns(pt);
ptIns.x += arW;
double delta(.01);
pTextV->setAlignmentPoint(AcGePoint3d(ptIns.x - delta, ptIns.y + lenghtV * .5 - deltaYV * .5, ptIns.z));
pTextH->setAlignmentPoint(AcGePoint3d(ptIns.x + lenghtH * .5 + deltaXV * .5, ptIns.y + deltaYH * .5 + delta, ptIns.z));
g_LayerMgr::instance().setLayer(pTextH, GLTools::gLayer_ZD_TEXT_SCALE);
g_LayerMgr::instance().setLayer(pTextV, GLTools::gLayer_ZD_TEXT_SCALE);
AddToTableRecord(pTextH, recID);
AddToTableRecord(pTextV, recID);
ptIns.x += deltaXV * .5;
AcGeVector3d vt;
AcGePoint3d ptEndH(AcGePoint3d::kOrigin);
AcGePoint3d ptEndV(AcGePoint3d::kOrigin);
float arL = arW * 100 / 33;
// 画横轴
vt.normalize();
vt = AcGeVector3d::kXAxis;
vt *= lenghtH;
ptEndH = ptIns + vt;
AcDbPolyline *pLineH = new AcDbPolyline;
pLineH->addVertexAt(0, AcGePoint2d(ptIns.x, ptIns.y));
pLineH->addVertexAt(1, AcGePoint2d(ptEndH.x, ptEndH.y), .0, arW, 0.);
vt.normalize();
vt *= lenghtH + arL;
ptEndH = ptIns + vt;
pLineH->addVertexAt(2, AcGePoint2d(ptEndH.x, ptEndH.y));
g_LayerMgr::instance().setLayer(pLineH, GLTools::gLayer_ZD_SCALE);
AddToTableRecord(pLineH, recID);
// 画纵轴
vt.normalize();
vt = AcGeVector3d::kYAxis;
vt *= lenghtV;
ptEndV = ptIns + vt;
AcDbPolyline *pLineV = new AcDbPolyline;
pLineV->addVertexAt(0, AcGePoint2d(ptIns.x, ptIns.y));
pLineV->addVertexAt(1, AcGePoint2d(ptEndV.x, ptEndV.y), 0., arW, .0);
vt.normalize();
vt *= lenghtV + arL;
ptEndV = ptIns + vt;
pLineV->addVertexAt(2, AcGePoint2d(ptEndV.x, ptEndV.y));
g_LayerMgr::instance().setLayer(pLineV, GLTools::gLayer_ZD_SCALE);
AddToTableRecord(pLineV, recID);
}
// 在 pt 点生成一个标尺和网格,以pt点位原点, 以dOrigin为起始标尺
// delta grid间距
// height 垂直总高
// width 水平总距离
// factor 为 现实高程与图纸坐标Y值的比例
// prec 刻度的小数个数
void drawGrid(AcDbObjectId &id
, const AcGePoint3d &ptOrigin
, const double dOrigin
, const int &ideltaYInterval
, const double &deltaY
, const double &deltaX
, const double &height
, const double &width
, const int &prec
, const float & textH
, const float & textWFactor
, LPCTSTR pszTextStyle
, double &dLeft // 标尺的 X 值
, double &dMid // 网格最左 X 值
, double &dRight // 网格最右 X 值
, double &dDown // 网格最下 Y 值
)
{
// 计算格子
double dSpace(g_rule_grid_space);
double _deltaY = deltaY * ideltaYInterval;
int h = int((width - dSpace) / deltaX);
int v = int(height / deltaY);
int v1 = int(height / _deltaY);
AcGeVector3d vtY(AcGeVector3d::kYAxis), vtX(AcGeVector3d::kXAxis);
vtX.normalize();
vtX *= dSpace;
vtY.normalize();
vtY *= _deltaY;
std::vector<AcGePoint3d> hpts(0);
hpts.push_back(ptOrigin + vtX);
AcGePoint3d ptUp(ptOrigin/* - vtX*/);
dLeft = ptUp.x;
int i(0);
for (i = 0; i < v1; ++i)
{
// 先向上
insertSegmentOfRuleline(id, ptUp, ptUp + vtY, i % 2 != 0);
insertRulelineText(id, ptUp, TypeConvert::f2s(dOrigin + (i * ideltaYInterval), &prec), i == 0 ? 1 : 256, textH, textWFactor, pszTextStyle);
ptUp += vtY;
}
insertRulelineText(id, ptUp, TypeConvert::f2s(dOrigin + (i * ideltaYInterval), &prec), i == 0 ? 1 : 256, textH, textWFactor, pszTextStyle);
vtY.normalize();
vtY *= deltaY;
ptUp = ptOrigin + vtX;
for (i = 0; i < v; ++i)
{
ptUp += vtY;
hpts.push_back(ptUp);
}
AcDbObjectIdArray ids;
AcDbObjectId entID;
// 画横线
vtX.normalize();
vtX *= h * deltaX;
AcDbLine *pL(NULL);
AcDbObjectId _id;
AcGePoint3d ptTemp(AcGePoint3d::kOrigin);
for (size_t i = 0; i < hpts.size(); ++i)
{
ptTemp = hpts[i];
pL = new AcDbLine(ptTemp, ptTemp + vtX);
g_LayerMgr::instance().setLayer(pL, GLTools::gLayer_ZD_GRID_LINE);
AddToTableRecord(pL, id, true, &_id);
ids.append(_id);
}
dMid = ptTemp.x;
dRight = ptTemp.x + vtX.length();
// 画纵线
vtX.normalize();
vtX *= deltaX;
vtY.normalize();
vtY *= (v)* deltaY;
AcGePoint3d ptS(*hpts.begin());
for (int i = 0; i < h + 1; ++i)
{
pL = new AcDbLine(ptS, ptS + vtY);
g_LayerMgr::instance().setLayer(pL, GLTools::gLayer_ZD_GRID_LINE);
AddToTableRecord(pL, id, true, &_id);
ptS += vtX;
ids.append(_id);
}
dDown = ptS.y;
ads_name ss;
acedSSAdd(NULL, NULL, ss);
for (long i = 0; i < ids.length(); ++i)
{
ads_name nn;
acdbGetAdsName(nn, ids[i]);
acedSSAdd(nn, ss, ss);
acedSSFree(nn);
}
SHacedCommand(RTSTR, _T(".DRAWORDER"), RTPICKS, ss, RTSTR, _T(""), RTSTR, _T("B"), RTSTR, _T(""), RTNONE);
acedSSFree(ss);
}
// 得到纵断的标志点,共三点,“设计道路端点” “上标程点” “下标程点”
void getMarkPoints(const AcDbObjectIdArray &arrIDs, std::map<AcGePoint3d, double, _compare_pt_y> &ptMap)
{
AecDbObjXDataMap xmap;
AcGePoint3d pt(AcGePoint3d::kOrigin);
double dY(.0);
for (int i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbPoint, pPt)
if (!pPt) continue;
if (!xmap.Read(pPt, _T("StaEl"))) continue;
if (!xmap.GetAt(_T("StaEl"), dY)) continue;
ptMap.insert(std::make_pair(pPt->position(), dY));
xmap.Empty();
OPENOBJ_END()
}
}
bool generateStakeRecordByFile(std::vector<CStakeRecord> &records)
{
CString sPath = FilePath::getSystemTemporaryFolder() + _T("\\") + STAKE_FILE_NAME;
if (_taccess(sPath, 0x0) != 0x0) return false;
CStdioFile file(sPath, CFile::shareDenyRead);
if (!file.m_hFile) return false;
std::vector<CString> stakes(0) // 桩号
, soils(0) // 管廊覆土
, topElev(0) // 管廊外顶标高
, currentGroundElev(0) // 现状地面高程
, designGroundElev(0) // 设计地面高程
, gradAndDistance(0) // 设计坡度与距离
, bottomInnerElev(0) // 管廊内底标高
, glStakes(0) // 管廊内底标高
, soilElev(0) // 覆土高度
, shEwVol(0) // 盾构体积
, guid(0) // GUID
;
CString sLine(_T(""));
std::vector<CString> vec(0);
while (file.ReadString(sLine))
{
vec.clear();
split(sLine, ' ', vec);
if (vec.empty()) continue;
if (vec[0].Compare(ZD_OUT::KEY_STAKENO) == 0)
stakes.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_SOIL) == 0)
soils.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_TOP_ELEV) == 0)
topElev.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_CURRENT_GROUND_ELEV) == 0)
currentGroundElev.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_DESIGN_GROUND_ELEV) == 0)
designGroundElev.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_GRADE_DISTANCE) == 0)
gradAndDistance.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_BOTTOM_INNER_ELEV) == 0)
bottomInnerElev.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_GL_STAKENO) == 0)
glStakes.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_SOIL_ELEV) == 0)
soilElev.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_NODE_GUID) == 0)
guid.assign(++vec.begin(), vec.end());
else if (vec[0].Compare(ZD_OUT::KEY_SH_EW_VOL) == 0)
shEwVol.assign(++vec.begin(), vec.end());
}
file.Close();
if (stakes.empty()) return false;
if (stakes.size() != soils.size()
|| stakes.size() != topElev.size()
|| stakes.size() != currentGroundElev.size()
|| stakes.size() != designGroundElev.size()) return false;
CStakeRecord record0(ZD_OUT::KEY_STAKENO, stakes, stakes);
CStakeRecord record1(ZD_OUT::KEY_SOIL, stakes, soils);
CStakeRecord record2(ZD_OUT::KEY_TOP_ELEV, stakes, topElev);
CStakeRecord record3(ZD_OUT::KEY_CURRENT_GROUND_ELEV, stakes, currentGroundElev);
CStakeRecord record4(ZD_OUT::KEY_DESIGN_GROUND_ELEV, stakes, designGroundElev);
CStakeRecord record5(ZD_OUT::KEY_GRADE_DISTANCE, gradAndDistance);
CStakeRecord record6(ZD_OUT::KEY_BOTTOM_INNER_ELEV, stakes, bottomInnerElev);
CStakeRecord record7(ZD_OUT::KEY_GL_STAKENO, stakes, glStakes);
CStakeRecord record8(ZD_OUT::KEY_SOIL_ELEV, stakes, soilElev);
CStakeRecord record9(ZD_OUT::KEY_NODE_GUID, stakes, guid);
CStakeRecord record10(ZD_OUT::KEY_SH_EW_VOL, stakes, shEwVol);
records.push_back(record0);
records.push_back(record1);
records.push_back(record2);
records.push_back(record3);
records.push_back(record4);
records.push_back(record5);
records.push_back(record6);
records.push_back(record7);
records.push_back(record8);
records.push_back(record9);
// 检查 "盾构体积" 是否有效,如有效,放入
for (size_t i = 0; i < shEwVol.size(); ++i)
{
double d = TypeConvert::s2f(shEwVol[i]);
if (!EQUAL_ZERO(d))
{
records.push_back(record10);
break;
}
}
return true;
}
void generateStakeInsertPoint(const AcDbObjectIdArray &arrIDs, CStakeRecord::StakeInsPts &stPts)
{
AecDbObjXDataMap xmap;
CString strStake(_T("")), strType(_T(""));
int fnType(0);
AcGePoint3d ptS(AcGePoint3d::kOrigin)
, ptE(AcGePoint3d::kOrigin)
, ptIns(AcGePoint3d::kOrigin);
int bCenterPt(0);
AcDbExtents ext, extAll;
CStakeRecord::StakeInsPts arCenPts;
for (int i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbEntity, pEnt)
if (!pEnt) continue;
if (AcDbBlockReference::cast(pEnt)) continue;
pEnt->getGeomExtents(ext);
extAll.addExt(ext);
if (!xmap.Read(pEnt, STAKE_SECTION)) continue;
if (!xmap.GetAt(STAKE_SEGMENT, strStake)) continue;
if (!xmap.GetAt(STAKE_TYPE, strType)) continue;
if (!xmap.GetAt(STAKE_FNTYPE, fnType)) continue;
// 直线上的起点和终点,哪一点的Y值小,取哪一点
AcDbPoint *pPt = AcDbPoint::cast(pEnt);
if (pPt)
{
if (xmap.GetAt(_T("CenterPoint"), bCenterPt) && fnType == kProModel)
{
ptIns = pPt->position();
arCenPts.insert(std::make_pair(strStake, ptIns));
}
else
{
ptIns = pPt->position();
stPts.insert(std::make_pair(strStake, ptIns));
}
}
xmap.Empty();
OPENOBJ_END()
}
for (CStakeRecord::StakeInsPts::iterator it = arCenPts.begin(); it != arCenPts.end(); ++it)
{
CString key(it->first);
CStakeRecord::StakeInsPts::iterator _it = stPts.find(key);
if (_it != stPts.end())
_it->second = it->second;
}
// 所有桩号的对应的点的Y值统一为最小值
for (CStakeRecord::StakeInsPts::iterator it = stPts.begin(); it != stPts.end(); ++it)
(it->second).y = extAll.minPoint().y;
}
void generateMileStoneRecord(const AcDbObjectIdArray &arrIDs, CStakeRecord &rec)
{
rec.setRecType(CStakeRecord::eMilestoneRec);
rec.setHeadString(ZD_OUT::KEY_MILESTONE);
AecDbObjXDataMap xmap;
std::set<CString> stakeSet;
CString strStake(_T("")), strType(_T(""));
int fnType(0);
CStakeRecord::_Data_ data;
for (int i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbEntity, pEnt)
if (!pEnt) continue;
if (!xmap.Read(pEnt, STAKE_SECTION)) continue;
if (!xmap.GetAt(STAKE_SEGMENT, strStake)) continue;
if (!xmap.GetAt(STAKE_TYPE, strType)) continue;
if (!xmap.GetAt(STAKE_FNTYPE, fnType)) continue;
if (fnType != kStackNode) continue;
if (!stakeSet.insert(strStake).second) continue;
data.stake = strStake;
data.sData = strStake;
rec.addData(data);
xmap.Empty();
OPENOBJ_END()
}
}
void analyFeatureString(LPCTSTR src, std::map<CString, std::vector<CString>> &features, std::vector<CString> &vfeatures)
{
std::vector<CString> v0(0); // <电力舱:xxx;xxx;xxx><燃气舱:xxx;xxx;xxx>...
std::vector<CString> v1(0); // <电力舱><xxx;xxx;xxx>
std::vector<CString> v2(0); // <电力舱><xxx;xxx;xxx>
split(src, _T('|'), v0);
if (v0.empty()) return;
vfeatures.assign(v0.begin(), v0.end());
std::pair<CString, std::vector<CString>> pr;
for (size_t i = 0; i < v0.size(); ++i)
{
pr.second.clear();
split(v0[i], _T(':'), v1);
if (v1.size() != 2) continue;
pr.first = v1[0];
split(v1[1], _T(';'), v2);
for (size_t j = 0; j < v2.size(); ++j)
{
pr.second.push_back(v2[j]);
}
features.insert(pr);
}
}
void generatekFeatureRecord(const AcDbObjectIdArray &arrIDs, CStakeRecord &rec)
{
rec.setRecType(CStakeRecord::eFeatureRec);
rec.setHeadString(ZD_OUT::KEY_FEATURE);
AecDbObjXDataMap xmap;
std::vector<CString>vecs(0);
std::pair<std::set<CString>::iterator, bool> pr;
CString strStake(_T("")), strType(_T(""));
int fnType(0);
CStakeRecord::_Data_ *pData(NULL), data;
std::map<CString, std::vector<CString>> features;
for (int i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbEntity, pEnt)
if (!pEnt) continue;
if (!xmap.Read(pEnt, STAKE_SECTION)) continue;
if (!xmap.GetAt(STAKE_SEGMENT, strStake)) continue;
if (!xmap.GetAt(STAKE_TYPE, strType)) continue;
if (!xmap.GetAt(STAKE_FNTYPE, fnType)) continue;
// 去掉变形缝
//if (fnType < kEspJoint || fnType > kProModel) continue;
if (fnType < kEspJoint + 1 || fnType > kProModel) continue;
data.clear();
if (fnType == kProModel)
{
features.clear();
vecs.clear();
analyFeatureString(strType, features, vecs);
if (rec.findData(strStake, pData))
{
for (size_t i = 0; i < vecs.size(); ++i)
pData->features.insert(vecs[i]);
}
else
{
data.stake = strStake;
for (size_t i = 0; i < vecs.size(); ++i)
data.features.insert(vecs[i]);
rec.addData(data);
}
}
else
{
if (rec.findData(strStake, pData))
{
pData->features.insert(strType);
}
else
{
data.stake = strStake;
data.features.insert(strType);
rec.addData(data);
}
}
xmap.Empty();
OPENOBJ_END()
}
}
// 得到存有所有实体的匿名块ID
AcDbObjectId getBlockID(const AcDbObjectIdArray &arrIDs)
{
AcDbExtents ext;
for (int i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbBlockReference, pEnt)
if (!pEnt) continue;
OPENOBJ_BEGIN(pEnt->blockTableRecord(), AcDb::kForRead, AcDbBlockTableRecord, pRc)
if (!pRc) continue;
if (pRc->isAnonymous()) // 匿名块
return pEnt->objectId();
OPENOBJ_END()
OPENOBJ_END()
return AcDbObjectId::kNull;
}
return AcDbObjectId::kNull;
}
// 得到所有实体的外接矩形
void getExtent(AcDbObjectId &idBlk, AcGePoint3d &ptMin, AcGePoint3d &ptMax)
{
AcDbExtents ext;
OPENOBJ_BEGIN(idBlk, AcDb::kForRead, AcDbBlockReference, pEnt)
if (!pEnt) return;
OPENOBJ_BEGIN(pEnt->blockTableRecord(), AcDb::kForRead, AcDbBlockTableRecord, pRc)
if (!pRc) return;
if (pRc->isAnonymous()) // 匿名块
pEnt->getGeomExtents(ext);
OPENOBJ_END()
OPENOBJ_END()
ptMin = ext.minPoint();
ptMax = ext.maxPoint();
}
// 缩放节点
typedef std::multimap<CString, AcDbObjectId>::iterator _IT;
void scaleNodes(_IT it1, _IT it2, const double &scale)
{
AcGePoint3d pt(AcGePoint3d::kOrigin);
AcDbExtents ext, extAll;
for (_IT it = it1; it != it2; ++it)
{
AcDbObjectId &id = it->second;
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt)
if (!pEnt) continue;
pEnt->getGeomExtents(ext);
extAll.addExt(ext);
OPENOBJ_END()
}
pt = extAll.minPoint();
pt.x += (extAll.maxPoint().x - extAll.minPoint().x) * .5;
AcGeMatrix3d mat;
mat.setToScaling(scale, pt);
for (_IT it = it1; it != it2; ++it)
{
AcDbObjectId &id = it->second;
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbEntity, pEnt)
if (!pEnt) continue;
pEnt->transformBy(mat);
OPENOBJ_END()
}
}
void scaleNodes(const AcDbObjectIdArray &arrIDs, const float &scale)
{
AcGeMatrix3d mat;
mat.setToScaling(scale);
int iType(0);
CString strID(_T(""));
AecDbObjXDataMap xmap;
std::multimap<CString, AcDbObjectId> idmaps;
for (int i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbEntity, pEnt)
if (!pEnt) continue;
if (AcDbBlockReference::cast(pEnt)) continue;
if (!xmap.Read(pEnt, STAKE_SECTION)) continue;
if (!xmap.GetAt(STAKE_FNTYPE, iType)) continue;
if (!xmap.GetAt(NODE_ID, strID)) continue;
if (pEnt->colorIndex() <= 0 || pEnt->colorIndex() > 6) continue;
if (iType == kPipeDoghouse
|| iType == kCableDoghouse
|| iType == kHeatDoghouse
|| iType == kVenDoghouse
|| iType == kEscapeHatch)
{
idmaps.insert(std::make_pair(strID, pEnt->objectId()));
}
xmap.Empty();
OPENOBJ_END()
}
_IT it(idmaps.begin());
std::pair<_IT, _IT> pr;
while (it != idmaps.end())
{
pr = idmaps.equal_range(it->first);
scaleNodes(pr.first, pr.second, scale);
it = pr.second;
}
}
double getFrameScaleD(const AcDbObjectIdArray &arrIDs)
{
AcGeScale3d scale;
CString str(_T(""));
for (size_t i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbBlockReference, pEnt)
if (!pEnt) continue;
OPENOBJ_BEGIN(pEnt->blockTableRecord(), AcDb::kForRead, AcDbBlockTableRecord, pRc)
if (!pRc) continue;
if (!pRc->isAnonymous()) // 非匿名块,即是图框块
{
scale = pEnt->scaleFactors();
return scale.sx;
}
OPENOBJ_END()
OPENOBJ_END()
}
return 1.;
}
CString getFrameScaleS(const AcDbObjectIdArray &arrIDs)
{
AcGeScale3d scale;
CString str(_T(""));
for (size_t i = 0; i < arrIDs.length(); ++i)
{
OPENOBJ_BEGIN(arrIDs[i], AcDb::kForRead, AcDbBlockReference, pEnt)
if (!pEnt) continue;
OPENOBJ_BEGIN(pEnt->blockTableRecord(), AcDb::kForRead, AcDbBlockTableRecord, pRc)
if (!pRc) continue;
if (!pRc->isAnonymous()) // 非匿名块,即是图框块
{
scale = pEnt->scaleFactors();
str.Format(_T("1:%d"), (int)(scale.sx * 1000));
return str;
}
OPENOBJ_END()
OPENOBJ_END()
}
return _T("1:1");
}
void collectEntityByXData(AcDbObjectId &recId, LPCTSTR pszSection, std::vector<AcDbObjectId> &ids)
{
if (!pszSection) return;
// 遍历所有实体,判断其扩展数据为桩号的直线,将其保存
Acad::ErrorStatus es;
AcDbEntity *pEnt(NULL);
AcDbBlockTableRecordIterator *pIter(NULL);
OPENOBJ_BEGIN(recId, AcDb::kForWrite, AcDbBlockTableRecord, pRec)
if (!pRec) return;
pRec->newIterator(pIter);
if (!pIter) return;
AecDbObjXDataMap xDataMap;
CString stakeNo(_T(""));
AcGePoint3d ptS(AcGePoint3d::kOrigin), ptE(AcGePoint3d::kOrigin);
for (pIter->start(); !pIter->done(); pIter->step())
{
es = pIter->getEntity(pEnt, AcDb::kForRead);
if (!pEnt) continue;
if (xDataMap.Read(pEnt, pszSection))
{
ids.push_back(pEnt->objectId());
}
pEnt->close();
}
OPENOBJ_END()
return;
}
AcGePoint3d getGeometryCenter(AcDbEntity *pEnt)
{
if (!pEnt) return AcGePoint3d::kOrigin;
AcDbExtents ext;
pEnt->getGeomExtents(ext);
return AcGePoint3d((ext.maxPoint().x + ext.minPoint().x) * .5
,(ext.maxPoint().y + ext.minPoint().y) * .5
, (ext.maxPoint().z + ext.minPoint().z) * .5);
}
CString getTraitString(LPCTSTR psz, const AcGePoint3d &pt)
{
if (!psz) return _T("");
CString str(psz);
str += TypeConvert::f2s(pt.x);
str += TypeConvert::f2s(pt.y);
str += TypeConvert::f2s(pt.z);
return str;
}
Acad::ErrorStatus transformBy(AcDbObjectId &id, AcGeMatrix3d mat)
{
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbEntity, pEnt)
if (pEnt)
return pEnt->transformBy(mat);
OPENOBJ_END()
return Acad::eInvalidInput;
}
}
//////////////////////////////////////////////////////////////////////////
#pragma region CStakeRecord
float CStakeRecord::m_dataTextHeight;
float CStakeRecord::m_dataTextFactor;
CString CStakeRecord::m_dataTextStyle;
float CStakeRecord::m_headTextHeight;
float CStakeRecord::m_headTextFactor;
CString CStakeRecord::m_headTextStyle;
double CStakeRecord::m_dTxtSpace = 1;
double CStakeRecord::m_dHeadTblTxtSpace = 1;
CStakeRecord::CStakeRecord(LPCTSTR head
, const std::vector<CString> &stakes
, const std::vector<CString> &data)
: m_sHead(head)
, m_type(eStringRec)
, m_datas(0)
{
if (stakes.size() != data.size()) return;
_Data_ d;
for (size_t i = 0; i < stakes.size(); ++i)
{
d.stake = stakes[i];
d.sData = data[i];
m_datas.push_back(d);
}
}
CStakeRecord::CStakeRecord(LPCTSTR head
, const std::vector<CString> &data)
: m_sHead(head)
, m_type(eGradRec)
, m_datas(0)
{
_Data_ d1, d2;
CString grade(_T("")), distance(_T("")), start(_T("")), end(_T(""));
for (size_t i = 0; i < data.size(); ++i)
{
analyGradeAndDistance(data[i], grade, distance, start, end);
d1.stake = start;
d1.sData = grade;
d2.stake = end;
d2.sData = distance;
m_datas.push_back(d1);
m_datas.push_back(d2);
}
}
double CStakeRecord::getHeadStringExtentX()
{
AcDbExtents ext;
AcDbText *p = generateText_H(m_sHead, m_headTextHeight, m_headTextFactor, m_headTextStyle);
if (p)
{
p->getGeomExtents(ext);
DELETE_PTR(p);
}
return ext.maxPoint().x - ext.minPoint().x;
}
double CStakeRecord::getHeadStringExtentY()
{
AcDbExtents ext;
AcDbText *p = generateText_H(m_sHead, m_headTextHeight, m_headTextFactor, m_headTextStyle);
if (p)
{
p->getGeomExtents(ext);
DELETE_PTR(p);
}
return ext.maxPoint().y - ext.minPoint().y;
}
double CStakeRecord::getMaxHeight()
{
AcDbText *p(NULL);
AcDbExtents result;
p = generateText_H(m_sHead, m_headTextHeight, m_headTextFactor, m_headTextStyle);
if (p)
{
result = getTextExtent(p);
DELETE_PTR(p);
}
if (m_type == eFeatureRec)
{
for (size_t i = 0; i < m_datas.size(); i++)
{
_Data_ &data = m_datas[i];
std::set<CString>::iterator it = data.features.begin();
for (; it != data.features.end(); ++it)
{
p = generateText_V(*it, m_dataTextHeight, m_dataTextFactor, m_dataTextStyle);
if (p)
{
result.addExt(getTextExtent(p));
DELETE_PTR(p);
}
}
}
}
else if (m_type != eGradRec)
{
for (size_t i = 0; i < m_datas.size(); i++)
{
_Data_ &data = m_datas[i];
p = generateText_V(data.sData, m_dataTextHeight, m_dataTextFactor, m_dataTextStyle);
if (p)
{
result.addExt(getTextExtent(p));
DELETE_PTR(p);
}
}
}
return result.maxPoint().y - result.minPoint().y + m_dTxtSpace;
}
void CStakeRecord::calcInsertPointY(const double &up, double &rowMaxH)
{
double delta(.2);
rowMaxH = getMaxHeight();
double down = up - rowMaxH;
double dTxtY = down + rowMaxH * .5;
for (size_t i = 0; i < m_datas.size(); ++i)
m_datas[i].pt.y = dTxtY;
m_ptHead.y = dTxtY;
}
double CStakeRecord::draw(
AcDbObjectId &id
, const double &preY
, const double &headW
, const double &dLeft
, const double &dMid
, const double &dRight
, const AcGeMatrix3d mat
)
{
m_ptHead.x = dLeft - headW * .5;
double rowMaxH;
calcInsertPointY(preY, rowMaxH);
AcDbText *pText = generateText_H(m_sHead, m_headTextHeight, m_headTextFactor, m_headTextStyle);
pText->setAlignmentPoint(m_ptHead);
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_ZD_TEXT_HEAD);
AddToTableRecord(pText, id);
// 共画8条线,四横四纵,包围 表头 和 数据
//////////////////////////////////////////////////////////////////////////
// 画数据长线
AcDbLine *pLine = new AcDbLine(AcGePoint3d(dLeft, preY, 0.), AcGePoint3d(dRight, preY, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
pLine = new AcDbLine(AcGePoint3d(dLeft, preY - rowMaxH, 0.), AcGePoint3d(dRight, preY - rowMaxH, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
// 两根数据短线
// pLine = new AcDbLine(AcGePoint3d(dMid, preY, 0.), AcGePoint3d(dMid, preY - rowMaxH, 0.));
// g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
// AddToTableRecord(pLine, id);
pLine = new AcDbLine(AcGePoint3d(dRight, preY, 0.), AcGePoint3d(dRight, preY - rowMaxH, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
//////////////////////////////////////////////////////////////////////////
// 再画2根短竖线
pLine = new AcDbLine(AcGePoint3d(dLeft, preY, 0.), AcGePoint3d(dLeft, preY - rowMaxH, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
pLine = new AcDbLine(AcGePoint3d(dLeft - headW, preY, 0.), AcGePoint3d(dLeft - headW, preY - rowMaxH, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
// 画2根短横线
pLine = new AcDbLine(AcGePoint3d(dLeft, preY - rowMaxH, 0.), AcGePoint3d(dLeft - headW, preY - rowMaxH, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
pLine = new AcDbLine(AcGePoint3d(dLeft, preY, 0.), AcGePoint3d(dLeft - headW, preY, 0.));
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TABLE_LINE);
AddToTableRecord(pLine, id);
//////////////////////////////////////////////////////////////////////////
if (m_type == eStringRec || m_type == eMilestoneRec)
{
// 绘制数据
for (size_t i = 0; i < m_datas.size(); ++i)
{
_Data_ &data = m_datas[i];
if (i != 0)
{
if (!InBox(data.pt, dRight, dMid))
continue;
}
pText = generateText_V(data.sData, m_dataTextHeight, m_dataTextFactor, m_dataTextStyle);
pText->setAlignmentPoint(data.pt);
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_ZD_TEXT_DATA);
pText->transformBy(mat);
AddToTableRecord(pText, id);
}
}
else if (m_type == eFeatureRec)
{
double x(0);
for (size_t i = 0; i < m_datas.size(); ++i)
{
_Data_ &data(m_datas[i]);
if (!InBox(data.pt, dRight, dMid)) continue;
if (data.features.empty()) continue;
x = data.pt.x;
std::set<CString>::iterator it = data.features.begin();
for (; it != data.features.end(); ++it)
{
pText = generateText_V(*it, m_dataTextHeight, m_dataTextFactor, m_dataTextStyle);
pText->setAlignmentPoint(AcGePoint3d(x, data.pt.y, .0));
pText->transformBy(mat);
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_ZD_TEXT_DATA);
AddToTableRecord(pText, id);
x += m_dataTextHeight;
}
}
}
else
{ // 绘制坡度
AcGePoint3d ptS(AcGePoint3d::kOrigin), ptE(AcGePoint3d::kOrigin), ptIns(AcGePoint3d::kOrigin);
AcDbExtents ext;
double w(.0), h(.0), delta(.1);
for (size_t i = 0; i < m_datas.size(); ++i)
{
_Data_ &data = m_datas[i];
if (!InBox(data.pt, dRight, dMid)) continue;
// 先画一条竖线
ptS.x = ptE.x = data.pt.x;
ptS.y = preY;
ptE.y = preY - rowMaxH;
pLine = new AcDbLine(ptS, ptE);
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_ZD_TEXT_DATA);
pLine->transformBy(mat);
AddToTableRecord(pLine, id);
pText = generateText_H(data.sData, m_dataTextHeight*.5f, m_dataTextFactor, m_dataTextStyle);
ptIns = data.pt;
pText->getGeomExtents(ext);
w = ext.maxPoint().x - ext.minPoint().x;
h = ext.maxPoint().y - ext.minPoint().y;
w *= .5;
h *= .5;
w += delta;
h += delta;
if (data.sData.Find(_T("%")) != -1)
{ // 有 "%" 为坡度数据,插入点向右移整段宽度的一半
ptIns.x += w;
ptIns.y += h;
}
else
{ // 无 "%" 为距离数据,插入点向左移整段宽度的一半
ptIns.x -= w;
ptIns.y += h;
}
pText->setAlignmentPoint(ptIns);
pText->transformBy(mat);
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_ZD_TEXT_DATA);
AddToTableRecord(pText, id);
}
}
return preY - rowMaxH;
}
void CStakeRecord::init(const StakeInsPts &dataSet)
{
// 从 dataSet 内找出需要的点
for (size_t i = 0; i < m_datas.size(); ++i)
{
_Data_ &data = m_datas[i];
StakeInsPts::const_iterator it = dataSet.find(data.stake);
// 文件中存在的数据,在图形中并没有实体对应
if (it == dataSet.end()) continue;
data.pt = it->second;
}
}
bool CStakeRecord::findData(const CString &stake, _Data_ *&data)
{
for (size_t i = 0; i < m_datas.size(); i++)
{
if (m_datas[i].stake.CompareNoCase(stake) == 0)
{
data = &m_datas[i];
return true;
}
}
return false;
}
void CStakeRecord::setStaticValue(const double &dScale)
{
// 数据字高
m_dataTextHeight = TypeConvert::s2f(getConfiguration(ZD_OUT::KEY_DATA_H)) * dScale;
// 数据宽度比例
m_dataTextFactor = TypeConvert::s2f(getConfiguration(ZD_OUT::KEY_DATA_W));
// 数据文字样式
m_dataTextStyle = getConfiguration(ZD_OUT::KEY_DATA_S);
// 行头字高
m_headTextHeight = TypeConvert::s2f(getConfiguration(ZD_OUT::KEY_HEAD_H)) * dScale;
// 行头宽度比例
m_headTextFactor = TypeConvert::s2f(getConfiguration(ZD_OUT::KEY_HEAD_W));
// 行头文字样式
m_headTextStyle = getConfiguration(ZD_OUT::KEY_HEAD_S);
m_dTxtSpace *= dScale;
m_dHeadTblTxtSpace *= dScale;
}
AcDbText* CStakeRecord::generateHeadText()
{
return generateText_H(m_sHead, m_headTextHeight, m_headTextFactor, m_headTextStyle);
}
AcDbText* CStakeRecord::generateText_V(LPCTSTR str, const float &dH, const float &dF, LPCTSTR style)
{
double dScale = getScale(_T("S2"));
AcDbText *pText = new AcDbText();
pText->setHeight(dH * dScale);
pText->setWidthFactor(dF);
pText->setRotation(PI * .5);
pText->setVerticalMode(AcDb::kTextVertMid);
pText->setHorizontalMode(AcDb::kTextCenter);
pText->setTextString(str);
AcDbObjectId idTextStyle = GLTools::getTextStyle(style);
if (!idTextStyle.isNull())
pText->setTextStyle(idTextStyle);
return pText;
}
AcDbText* CStakeRecord::generateText_H(LPCTSTR str, const float &dH, const float &dF, LPCTSTR style)
{
double dScale = getScale(_T("S2"));
AcDbText *pText = new AcDbText();
pText->setHeight(dH * dScale);
pText->setWidthFactor(dF);
pText->setHorizontalMode(AcDb::kTextMid);
pText->setTextString(str);
AcDbObjectId idTextStyle = GLTools::getTextStyle(style);
if (!idTextStyle.isNull())
pText->setTextStyle(idTextStyle);
return pText;
}
AcDbExtents CStakeRecord::getTextExtent(AcDbText *p)
{
AcDbExtents ext;
if (p)
p->getGeomExtents(ext);
return ext;
}
#pragma endregion CStakeRecord
namespace ZD_OUT
{
void getDataRecords(AcDbObjectIdArray &arrIDs
, std::vector<CStakeRecord> &records)
{
records.clear();
if (arrIDs.isEmpty()) return;
CStakeRecord::setStaticValue(getFrameScaleD(arrIDs));
// 得到空间中存在的桩号的插入点
CStakeRecord::StakeInsPts stPts;
generateStakeInsertPoint(arrIDs, stPts);
if (stPts.empty())
{
acutPrintf(_T("\n未能在图形中提取出桩号信息。"));
return;
}
// 得到桩号所对应的数据,从文件中。
std::vector<CStakeRecord> recs(0);
if (!generateStakeRecordByFile(recs))
{
acutPrintf(_T("\n未在本地找到桩号数据。"));
return;
}
// 里程节点记录
CStakeRecord rec;
generateMileStoneRecord(arrIDs, rec);
recs.push_back(rec);
// 特征节点记录
CStakeRecord rec1;
generatekFeatureRecord(arrIDs, rec1);
recs.push_back(rec1);
// 初始化插入点
for (size_t i = 0; i < recs.size(); ++i)
recs[i].init(stPts);
// 按 rules顺序进行输出
for (size_t i = 0; i < g_config.size(); ++i)
{
std::vector<CStakeRecord>::iterator it = std::find_if(recs.begin(), recs.end(), CStakeRecord::compare(g_config[i].first));
if (it != recs.end())
{
if (g_config[i].second.CompareNoCase(_T("0")) != 0)
records.push_back(*it);
}
}
}
void insertZDTable(AcDbObjectId &recId
, AcDbObjectIdArray &arrIDs
, std::vector<CStakeRecord> &records
, const AcGePoint3d &_ptMin
, const AcGePoint3d &_ptMax
, const bool &bEnd // 最后一次调用
)
{
if (arrIDs.isEmpty()) return;
if (!recId.isValid()) return;
if (records.empty()) return;
double dScaleH(getFrameScaleD(arrIDs));
readConfiguration();
// 网格设置参数
int i_wg_grid_interval(TypeConvert::s2i(getConfiguration(KEY_GRID_INTERVAL)));
int i_wg_prec(TypeConvert::s2i(getConfiguration(KEY_GRID_PREC)));
float f_wg_arrow_w(TypeConvert::s2f(getConfiguration(KEY_ARROW_W)));
float f_wg_grid_h(TypeConvert::s2f(getConfiguration(KEY_GRID_H)) * dScaleH);
CString s_wg_grid_s(getConfiguration(KEY_GRID_S));
float f_wg_grid_w(TypeConvert::s2f(getConfiguration(KEY_GRID_W)));
float f_wg_ratio_h(TypeConvert::s2f(getConfiguration(KEY_RATIO_H)) * dScaleH);
CString s_wg_ratio_s(getConfiguration(KEY_RATIO_S));
float f_wg_ratio_w(TypeConvert::s2f(getConfiguration(KEY_RATIO_W)));
// 引出标注设置参数
float f_ycbz_h(TypeConvert::s2f(getConfiguration(KEY_YCBZ_H)));
CString f_ycbz_s(getConfiguration(KEY_YCBZ_S));
// 节点设置参数
float f_jd_scale(TypeConvert::s2f(getConfiguration(KEY_NODE_SCALE)));
//////////////////////////////////////////////////////////////////////////
// 下面代码绘制网格标尺
// 先取出三个特征点,三个特征点用来计算真实高程
std::map<AcGePoint3d, double, _compare_pt_y> ptMap;
getMarkPoints(arrIDs, ptMap);
if (ptMap.size() != 3) return;
std::map<AcGePoint3d, double, _compare_pt_y>::iterator it(ptMap.begin());
AcGePoint3d ptDown(it->first);
double dDown(it->second);
++it;
AcGePoint3d ptUp(it->first);
double dUp(it->second);
++it;
AcGePoint3d ptRoad(it->first);
double dRoad(it->second);
//drawCircle(recId, ptUp, 5);
//drawCircle(recId, ptDown, 5);
// 得到所有实体的范围
AcDbObjectId idBlk = getBlockID(arrIDs); // 所有实体都在此块中
AcGePoint3d ptMin(AcGePoint3d::kOrigin), ptMax(AcGePoint3d::kOrigin);
getExtent(idBlk, ptMin, ptMax);
AcGePoint3d ptMinBk(ptMin), ptMaxBk(ptMax);
//drawCircle(recId, ptMin, 1);
//drawCircle(recId, ptMax, 1);
// factor 为 现实高程差与图纸坐标Y值差的比
double factorY = (dUp - dDown) / (ptUp.y - ptDown.y);
double factorX = dScaleH;
double deltaY = 1 / factorY;
double deltaX = deltaY;
//////////////////////////////////////////////////////////////////////////
// 下面输出计算数据
AcDbExtents extHead;
double dHeadW(.0), dHeadDelta(.0), dTblH(.0);
for (size_t i = 0; i < records.size(); ++i)
{
CStakeRecord &rec = records[i];
AcDbText *pText = rec.generateHeadText();
if (!pText) continue;
AcDbExtents ext;
pText->getGeomExtents(ext);
extHead.addExt(ext);
DELETE_PTR(pText);
dTblH += records[i].getMaxHeight();
}
dHeadDelta = extHead.maxPoint().x - extHead.minPoint().x;
dHeadW = dHeadDelta + CStakeRecord::m_dTxtSpace;
// 根据 dHeadW 重新计算 dLeft
AcGePoint3d ptInsMin(AcGePoint3d::kOrigin);
double dLeft, dMid, dRight;
ptInsMin.x = _ptMin.x - g_rule_grid_space;
// 把 ptInsMin.y 算一下,用最小的Y值加表格高度,再加一个间隙
ptInsMin.y = _ptMin.y + dTblH + 1;
// dMinDown 为标尺左下角高程
double dMinDown = dDown - factorY * (ptDown.y - ptInsMin.y);
// iDown 为取整后的dMinDown
int iDown(0);
if (dMinDown - (int)(dMinDown) < 1e-6)
iDown = (int)(dMinDown);
else
iDown = (int)(dMinDown) + 1;
// 根据 iDown 算出坐标
ptInsMin.y = ptDown.y - (dDown - iDown) / factorY;
drawGrid(recId
, ptInsMin
, iDown
, i_wg_grid_interval
, deltaY
, deltaX
, _ptMax.y - ptInsMin.y + deltaY
, _ptMax.x - ptInsMin.x + deltaY
, i_wg_prec
, f_wg_grid_h
, f_wg_grid_w
, s_wg_grid_s
, dLeft
, dMid
, dRight
, dDown);
// 将存有实体的块移动到网格处
AcGeVector3d vtMove(AcGeVector3d::kXAxis);
vtMove *= dMid - ptMinBk.x;
g_content_blk_mat.setToIdentity();
g_content_blk_mat.setTranslation(vtMove);
if (bEnd)
transformBy(idBlk, g_content_blk_mat);
double preY(_ptMin.y + dTblH);
for (size_t i = 0; i < records.size(); ++i)
preY = records[i].draw(recId, preY, dHeadW, dLeft, dMid, dRight, g_content_blk_mat);
// 缩放节点
scaleNodes(arrIDs, f_jd_scale);
// 绘制比例尺
double dHLength(.0), dVLength(.0);
CString strV(getScaleS2());
CString strH = getFrameScaleS(arrIDs);
AcGePoint3d ptRule(dLeft - dHeadW, dDown, 0);
drawScaleRule(recId, ptRule, strH, strV, f_wg_arrow_w, f_wg_ratio_h, f_wg_ratio_w, s_wg_ratio_s);
if (bEnd)
{
g_prRang.first = _ptMin.x;
g_prRang.second = _ptMax.x;
}
}
bool readConfiguration()
{
return ::readConfiguration();
}
CString getConfiguration(LPCTSTR key)
{
return ::getConfiguration(key);
}
void getConfiguration(std::vector<std::pair<CString, CString>> &v)
{
v.assign(g_config.begin(), g_config.end());
}
void insertDimension(AcDbObjectId &recId)
{
std::vector<AcDbObjectId> ids;
collectEntityByXData(recId, STAKE_SECTION, ids);
if (ids.empty()) return;
CString strType(_T("")), strID(_T("")), strTextStyle(getConfiguration(KEY_YCBZ_S));
if (strTextStyle.IsEmpty())
strTextStyle = _T("standard");
float textH(TypeConvert::s2f(getConfiguration(KEY_YCBZ_H)));
int nDimByStake(TypeConvert::s2i(getConfiguration(KEY_NODE_DIMTYPE)));
AcGePoint3d ptIns(AcGePoint3d::kOrigin), pt2(AcGePoint3d::kOrigin);
std::set<CString> strSet1;
std::pair<std::set<CString>::iterator, bool> pr;
AcDbEntity *pDim(NULL);
AcGePoint3d ptMax(AcGePoint3d::kOrigin), ptMin(AcGePoint3d::kOrigin);
EWNodeDimInfos nds;
catalogNodeType(ids, nds);
int nCharLen(0);
std::multiset<CString> mmapStrs;
typedef std::multiset<CString>::iterator mmapIt;
std::pair<mmapIt, mmapIt> _pr;
size_t dif(0);
std::wstringstream ss;
std::vector<EWNodeDimInfo> vnds(0);
for (EWNodeDimInfos::iterator it = nds.begin(); it != nds.end(); ++it)
{
vnds.push_back(it->second);
}
std::sort(vnds.begin(), vnds.end(), EWNodeDimInfo::_com_by_x());
// first 管廊长度,second.first 管廊起始桩号,second.second 管廊结束桩号
std::map<CString, double> guids;
if (TypeConvert::s2i(getConfiguration(KEY_NODE_DIMTYPE)) != 1)
{
std::vector<CStakeRecord> recs(0);
if (!generateStakeRecordByFile(recs))
{
acutPrintf(_T("\n未在本地找到桩号数据。"));
return;
}
if (recs.size() < 9) return;
CStakeRecord recDist(recs[7]);
CStakeRecord recGuid(recs[9]);
if (recDist.m_datas.size() == recGuid.m_datas.size())
{
double d;
for (size_t i = 0; i < recDist.m_datas.size() - 1; i++)
{
StakeTools::analyStakeString(recDist.m_datas[i].sData, d);
guids.insert(std::make_pair(recGuid.m_datas[i].sData, d));
}
}
}
CString strDim(_T(""));
double dStake(.0);
for (std::vector<EWNodeDimInfo>::iterator it = vnds.begin(); it != vnds.end(); ++it)
{
ss.str(_T(""));
mmapStrs.insert(it->strType);
_pr = std::equal_range(mmapStrs.begin(), mmapStrs.end(), it->strType);
dif = std::distance(_pr.first, _pr.second);
ss << dif;
ptMax = it->ext.maxPoint();
ptMin = it->ext.minPoint();
ptIns.x = (ptMax.x + ptMin.x) * .5;
ptIns.y = (ptMax.y + ptMin.y) * .5;
pr = strSet1.insert(getTraitString(it->strType, ptIns));
if (!pr.second) continue;
pt2 = ptIns;
pt2.y += (ptMax.y - ptMin.y) * .5 + 1;
if (it->fnType == kFirwWall)
pt2.y += 5;
nCharLen = it->strType.GetLength();
// 在这里判断是否需要根据距离来标注节点
strDim = it->strStake;
if (TypeConvert::s2i(getConfiguration(KEY_NODE_DIMTYPE)) != 1)
{
std::map<CString, double>::iterator mIt(guids.end());
mIt = guids.find(it->strID);
if (mIt != guids.end())
strDim = StakeTools::generateStakeString(mIt->second, _T("L"));
}
//pDim = MK_DIM::makeSymbNode(ptIns
#ifndef ZWCAD
pDim = DimFactory(FilePath::GetArxDir() + _T("//dimension.arx")).makeSymbNode(ptIns
#else
pDim = DimFactory(FilePath::GetArxDir() + _T("//dimension.zrx")).makeSymbNode(ptIns
#endif
, pt2
, nCharLen * .7
, strDim + _T(":") + it->strName + _T(" ") + it->strType + ss.str().c_str()
, strTextStyle
, textH
//, MK_DIM::eNoneArrow
, DimFactory::eNoneArrow
, 3.
//, MK_DIM::eBeginAlign);
, DimFactory::eBeginAlign);
if (!pDim) continue;
if (ptIns.x > g_prRang.first)
pDim->transformBy(g_content_blk_mat);
g_LayerMgr::instance().setLayer(pDim, GLTools::gLayer_ZD_DIM);
AddToTableRecord(pDim, recId);
}
// 在这里删除所有多余点
for (size_t i = 0; i < ids.size(); ++i)
{
AcDbObjectId &id = ids[i];
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbEntity, pEnt)
if (pEnt) pEnt->erase();
OPENOBJ_END()
}
}
// 网格最左侧(不算标尺)与表格最左侧的距离(+1)
double getGridLeftPointDist()
{
std::vector<CStakeRecord> recs(0);
CStakeRecord rec;
rec.setHeadString(ZD_OUT::KEY_STAKENO);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_SOIL);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_TOP_ELEV);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_CURRENT_GROUND_ELEV);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_DESIGN_GROUND_ELEV);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_GRADE_DISTANCE);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_GRADE);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_DISTANCE);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_FEATURE);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_MILESTONE);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_BOTTOM_INNER_ELEV);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_GL_STAKENO);
recs.push_back(rec);
rec.setHeadString(ZD_OUT::KEY_SOIL_ELEV);
recs.push_back(rec);
std::vector<CStakeRecord> records(0);
for (size_t i = 0; i < g_config.size(); ++i)
{
std::vector<CStakeRecord>::iterator it = std::find_if(recs.begin(), recs.end(), CStakeRecord::compare(g_config[i].first));
if (it != recs.end())
{
if (g_config[i].second.CompareNoCase(_T("0")) != 0)
records.push_back(*it);
}
}
AcDbExtents extHead;
double dHeadW(.0), dHeadDelta(.0);
for (size_t i = 0; i < records.size(); ++i)
{
CStakeRecord &rec = records[i];
AcDbText *pText = rec.generateHeadText();
if (!pText) continue;
AcDbExtents ext;
pText->getGeomExtents(ext);
extHead.addExt(ext);
DELETE_PTR(pText);
}
dHeadDelta = extHead.maxPoint().x - extHead.minPoint().x;
dHeadW = dHeadDelta + CStakeRecord::m_dTxtSpace + g_rule_grid_space + CStakeRecord::m_dHeadTblTxtSpace;
return dHeadW;
}
}