3325 lines
88 KiB
C++
3325 lines
88 KiB
C++
#include "stdafx.h"
|
||
#include "stdarx.h"
|
||
#include <algorithm>
|
||
#include "stakeoper.h"
|
||
#include "dbtable.h"
|
||
#include "UITools.h"
|
||
#include "aecdbObjXDataMap.h"
|
||
#include "KTModelLayoutXData.h"
|
||
#include "UITools.h"
|
||
#include "KTSetting.h"
|
||
#include "KTCadUtility.h"
|
||
#include "KTCadUtilityEx.h"
|
||
#include <set>
|
||
#include "ZDSZDlg.h"
|
||
#include "XGLCDlg.h"
|
||
#include "AecDbEarthWorm.h"
|
||
#include "KTFKDlg.h"
|
||
#include "CTSKDlg.h"
|
||
#include "AecDbVenDoghouse.h"
|
||
#include "MakeDim.h"
|
||
#include "AecDb3dRoadAxisLine.h"
|
||
#include "TQBGDlg.h"
|
||
#include "EWCheckerData.h"
|
||
#include "GenerateStakeDlg.h"
|
||
#include "GiDrawutility.h"
|
||
#include "DGGLDlg.h"
|
||
#include "insertEqu.h"
|
||
#include "crackEntitytools.h"
|
||
|
||
extern void PushGripMessage(GripMessage& msg);
|
||
|
||
namespace
|
||
{
|
||
#define TEXT_STYLE _T("Pipe_Dim")
|
||
}
|
||
|
||
namespace
|
||
{
|
||
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);
|
||
}
|
||
|
||
CString IDCreate()
|
||
{
|
||
CString sID = _T("");
|
||
|
||
GUID Guid;
|
||
static TCHAR szGuid[39];
|
||
RPC_WSTR pszGuid = NULL;
|
||
UuidCreate(&Guid);
|
||
|
||
if (RPC_S_OK != UuidToString(&Guid, &pszGuid))
|
||
{
|
||
return _T("");
|
||
}
|
||
|
||
lstrcpyn(szGuid, (TCHAR *)pszGuid, sizeof(szGuid));
|
||
RpcStringFree(&pszGuid);
|
||
|
||
szGuid[38] = _T('\0');
|
||
sID = szGuid;
|
||
sID.MakeUpper();
|
||
return sID;
|
||
}
|
||
|
||
void FreeBuffer(int n, const AcDbVoidPtrArray& arEntPtrs)
|
||
{
|
||
AcDbEntity* pEnt = NULL;
|
||
for (int i = n; i < arEntPtrs.length(); i++)
|
||
{
|
||
pEnt = (AcDbEntity*)arEntPtrs.at(i);
|
||
DELETE_PTR(pEnt);
|
||
}
|
||
}
|
||
|
||
Acad::ErrorStatus AddToModelSpace(AcDbEntity* pEnt, AcDbDatabase* pDb = NULL, bool bClose = true)
|
||
{
|
||
if (pDb == NULL)
|
||
pDb = acdbHostApplicationServices()->workingDatabase();
|
||
|
||
Acad::ErrorStatus es;
|
||
|
||
AcDbBlockTable* pTbl = NULL;
|
||
if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead)))
|
||
{
|
||
AcDbBlockTableRecord* pBTR = NULL;
|
||
if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite)))
|
||
{
|
||
es = pBTR->appendAcDbEntity(pEnt);
|
||
if (bClose)
|
||
pEnt->close();
|
||
|
||
pBTR->close();
|
||
}
|
||
pTbl->close();
|
||
}
|
||
return es;
|
||
}
|
||
|
||
bool AddToTableRecord(AcDbEntity* pEnt, AcDbObjectId &id, bool bClose = true)
|
||
{
|
||
if (!pEnt) return false;
|
||
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbBlockTableRecord, pRec)
|
||
if (!pRec) return false;
|
||
pRec->appendAcDbEntity(pEnt);
|
||
if (bClose) pEnt->close();
|
||
OPENOBJ_END()
|
||
return true;
|
||
}
|
||
|
||
double getPrinterWidth()
|
||
{
|
||
AecDbObjXDataMap xDataMap;
|
||
KTModelLayoutXData::ReadModelXData(_T("EW_EARTHWORMINIT"), xDataMap);
|
||
CString w(_T("1.5"));
|
||
xDataMap.GetAt(_T("w1"), w);
|
||
return _ttof(w);
|
||
}
|
||
|
||
bool poly3D2Poly2D(AcDbObjectId &id, AcDbPolyline &poly)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDb3dPolyline, p3D)
|
||
if (!p3D) return false;
|
||
AcGePoint3d ptGe;
|
||
AcGePoint3dArray pts;
|
||
CStringArray stakes;
|
||
CString strValue;
|
||
|
||
AcDbObjectIterator* pIt = p3D->vertexIterator();
|
||
if (!pIt) return false;
|
||
|
||
int i(0);
|
||
for (pIt->start(); !pIt->done(); pIt->step())
|
||
{
|
||
AcDb3dPolylineVertex* pVtx = NULL;
|
||
if (Acad::eOk != p3D->openVertex(pVtx, pIt->objectId(), AcDb::kForRead)) continue;
|
||
ptGe = pVtx->position();
|
||
poly.addVertexAt(i, ptGe.convert2d(AcGePlane::kXYPlane));
|
||
++i;
|
||
}
|
||
DELETE_PTR(pIt);
|
||
OPENOBJ_END()
|
||
return true;
|
||
}
|
||
|
||
CString pt2String(const AcGePoint3d &pt)
|
||
{
|
||
CString str(_T(""));
|
||
str.Format(_T("%.3f%.3f%.3f"), pt.x, pt.y, pt.z);
|
||
return str;
|
||
}
|
||
|
||
// 取与d最接近的,10的倍数。例:124.789 -> 130.000
|
||
double roundUpNum(const double &d, const int &base)
|
||
{
|
||
if (EQUAL_ZERO(d)) return d;
|
||
if (d < base) return base;
|
||
double dd(d);
|
||
dd /= base;
|
||
dd = (int)dd;
|
||
dd *= base;
|
||
if (EQUAL(dd, d))
|
||
return dd;
|
||
dd += base;
|
||
return dd;
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
// 得到AcDbText的插入位置,position()/alignmentPoint()
|
||
AcGePoint3d getDbTextPos(AcDbText *pTxt)
|
||
{
|
||
if (!pTxt) return AcGePoint3d::kOrigin;
|
||
if (pTxt->horizontalMode() == AcDb::kTextLeft && pTxt->verticalMode() == AcDb::kTextBase)
|
||
return pTxt->position();
|
||
else
|
||
{
|
||
AcGePoint3d pt = pTxt->alignmentPoint();
|
||
AcGePoint3d ptPos = pTxt->position();
|
||
double dRot = pTxt->rotation();
|
||
AcGeVector3d vt(AcGeVector3d::kXAxis);
|
||
vt.rotateBy(dRot, AcGeVector3d::kZAxis);
|
||
AcDbXline line;
|
||
line.setBasePoint(ptPos);
|
||
line.setUnitDir(vt);
|
||
AcGePoint3d ptRes(pt);
|
||
line.getClosestPointTo(pt, ptRes);
|
||
return ptRes;
|
||
}
|
||
return AcGePoint3d::kOrigin;
|
||
}
|
||
|
||
AcDbObjectId insert3dPoly(const std::vector<std::pair<AcGePoint3d, CString>> &pts)
|
||
{
|
||
if (pts.empty()) return AcDbObjectId::kNull;
|
||
AcDb3dPolyline *pPoly3d = new AcDb3dPolyline();
|
||
|
||
CString strPt(_T(""));
|
||
for (size_t i = 0; i < pts.size(); ++i)
|
||
{
|
||
AecDbObjXDataMap xmap;
|
||
const AcGePoint3d &pt(pts[i].first);
|
||
AcDb3dPolylineVertex *pVer = new AcDb3dPolylineVertex;
|
||
pVer->setPosition(pt);
|
||
pPoly3d->appendVertex(pVer);
|
||
pPoly3d->setColorIndex(1);
|
||
xmap.SetAt(_T("stake"), pts[i].second);
|
||
xmap.Write(pVer, _T("PL3D_STAKENO"));
|
||
}
|
||
|
||
g_LayerMgr::instance().setLayer(pPoly3d, GLTools::gLayer_ELEV);
|
||
|
||
AddToModelSpace(pPoly3d, NULL, true);
|
||
return pPoly3d->objectId();
|
||
}
|
||
|
||
void outputTXTFile(const std::vector<std::pair<AcGePoint3d, CString>> &pts, LPCTSTR pszFilter)
|
||
{
|
||
if (pts.empty()) return;
|
||
|
||
CString szFilter(pszFilter);
|
||
CFileDialog fileDlg(FALSE, _T("stl"), NULL, OFN_HIDEREADONLY, szFilter, acedGetAcadFrame());
|
||
if (fileDlg.DoModal() != IDOK) return;
|
||
|
||
CStdioFile file(fileDlg.GetPathName(), CFile::modeCreate | CFile::modeWrite);
|
||
if (!file.m_hFile) return;
|
||
CString str(_T(""));
|
||
for (size_t i = 0; i < pts.size(); ++i)
|
||
{
|
||
str.Format(_T("%s,%.3f\n"), pts[i].second, pts[i].first.z);
|
||
file.WriteString(str);
|
||
}
|
||
file.Close();
|
||
}
|
||
|
||
void generateDwgCuter(AcDbPolyline &poly, AcGePoint3d ptStart, const double &dSpace, const double &dWidth)
|
||
{
|
||
AcGePoint3d pt(AcGePoint3d::kOrigin);
|
||
AcGeVector3d vt, vtt;
|
||
std::vector<AcGePoint3d> pts(0);
|
||
std::vector<AcGeVector3d> vts(0);
|
||
|
||
double lengthS(.0), lengthE(.0), length(.0), len(.0);
|
||
poly.getEndPoint(pt);
|
||
poly.getDistAtPoint(pt, lengthE);
|
||
poly.getStartPoint(pt);
|
||
poly.getDistAtPoint(pt, lengthS);
|
||
length = abs(lengthE - lengthS);
|
||
poly.getDistAtPoint(ptStart, len);
|
||
while (len < length)
|
||
{
|
||
poly.getPointAtDist(len, pt);
|
||
len += dSpace;
|
||
pts.push_back(pt);
|
||
poly.getFirstDeriv(pt, vt);
|
||
vt.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
vts.push_back(vt);
|
||
}
|
||
|
||
AcDbObjectId styleID = GLTools::getTextStyle(TEXT_STYLE);
|
||
|
||
double subLen = dWidth * .08;
|
||
double textH = 3.0;
|
||
double textAngle(.0);
|
||
double textWF(.7);
|
||
double lineW = 0; getPrinterWidth();
|
||
double textW1(.0), textW2(.0);
|
||
AcGePoint3d ptS(AcGePoint3d::kOrigin)
|
||
, ptE(AcGePoint3d::kOrigin)
|
||
, ptSubS(AcGePoint3d::kOrigin)
|
||
, ptSubE(AcGePoint3d::kOrigin);
|
||
|
||
CString str1(_T("")), str2(_T(""));
|
||
|
||
for (size_t i = 0; i < vts.size(); ++i)
|
||
{
|
||
pt = pts[i];
|
||
vt = vts[i];
|
||
vt.normalize();
|
||
vt *= dWidth * .5;
|
||
ptSubS = ptS = pt + vt;
|
||
ptSubE = ptE = pt - vt;
|
||
AcDbPolyline *pLine = new AcDbPolyline;
|
||
pLine->addVertexAt(0, AcGePoint2d(ptS.x, ptS.y), 0., lineW, lineW);
|
||
pLine->addVertexAt(1, AcGePoint2d(ptE.x, ptE.y), 0., lineW, lineW);
|
||
AddToModelSpace(pLine);
|
||
vt = ptS - ptE;
|
||
vt.normalize();
|
||
vt *= subLen;
|
||
ptSubS -= vt;
|
||
ptSubE += vt;
|
||
vt.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
vt.normalize();
|
||
vt *= subLen * .5;
|
||
pLine = new AcDbPolyline;
|
||
pLine->addVertexAt(0, (ptSubS + vt).convert2d(AcGePlane::kXYPlane), 0., lineW, lineW);
|
||
pLine->addVertexAt(1, (ptSubS - vt).convert2d(AcGePlane::kXYPlane), 0., lineW, lineW);
|
||
AddToModelSpace(pLine);
|
||
pLine = new AcDbPolyline;
|
||
pLine->addVertexAt(0, (ptSubE + vt).convert2d(AcGePlane::kXYPlane), 0., lineW, lineW);
|
||
pLine->addVertexAt(1, (ptSubE - vt).convert2d(AcGePlane::kXYPlane), 0., lineW, lineW);
|
||
AddToModelSpace(pLine);
|
||
|
||
str1.Format(_T("%d"), i + 1);
|
||
str2.Format(_T("%d"), i + 2);
|
||
|
||
textAngle = AcGeVector3d::kXAxis.angleTo(vt, AcGeVector3d::kZAxis) + PI;
|
||
|
||
AcDbExtents ext1, ext2;
|
||
|
||
AcDbText *pText1 = new AcDbText;
|
||
pText1->setTextString(str1);
|
||
if (styleID.isValid())
|
||
pText1->setTextStyle(styleID);
|
||
pText1->setHeight(textH);
|
||
pText1->setWidthFactor(textWF);
|
||
pText1->setHorizontalMode(AcDb::kTextMid);
|
||
pText1->getGeomExtents(ext1);
|
||
pText1->setRotation(textAngle);
|
||
|
||
AcDbText *pText11 = (AcDbText*)pText1->clone();
|
||
|
||
AcDbText *pText2 = (AcDbText*)pText1->clone();
|
||
pText2->setTextString(str2);
|
||
pText2->setRotation(.0);
|
||
pText2->getGeomExtents(ext2);
|
||
pText2->setRotation(textAngle);
|
||
|
||
AcDbText *pText22 = (AcDbText*)pText1->clone();
|
||
pText22->setTextString(str2);
|
||
|
||
textW1 = ext1.maxPoint().x - ext1.minPoint().x;
|
||
textW2 = ext2.maxPoint().x - ext2.minPoint().x;
|
||
|
||
vtt = vt;
|
||
|
||
vt.normalize();
|
||
vt *= subLen * .5 + textW1 * .75;
|
||
pText1->setAlignmentPoint(ptSubS + vt);
|
||
pText11->setAlignmentPoint(ptSubE + vt);
|
||
|
||
vtt.normalize();
|
||
vtt *= subLen * .5 + textW2 * .75;
|
||
pText2->setAlignmentPoint(ptSubS - vtt);
|
||
pText22->setAlignmentPoint(ptSubE - vtt);
|
||
|
||
AddToModelSpace(pText1);
|
||
AddToModelSpace(pText11);
|
||
AddToModelSpace(pText2);
|
||
AddToModelSpace(pText22);
|
||
}
|
||
}
|
||
|
||
void getXLineByDbText(AcDbObjectId id, AcDbXline *pLine)
|
||
{
|
||
if (!pLine) return;
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pText)
|
||
if (!pText) return;
|
||
|
||
bool b;
|
||
CString str;
|
||
double d;
|
||
AcGePoint3d pos(AcGePoint3d::kOrigin);
|
||
if (!StakeTools::readSHSStake(pText, pos, b, str, d, d))
|
||
{
|
||
AcDb::TextHorzMode hm = pText->horizontalMode();
|
||
AcDb::TextVertMode vm = pText->verticalMode();
|
||
|
||
if (hm == AcDb::kTextLeft && vm == AcDb::kTextBase)
|
||
pos = pText->position();
|
||
else
|
||
pos = pText->alignmentPoint();
|
||
}
|
||
|
||
double angle = pText->rotation();
|
||
AcGeVector3d vt(AcGeVector3d::kXAxis);
|
||
vt.rotateBy(angle, AcGeVector3d::kZAxis);
|
||
pLine->setBasePoint(pos);
|
||
pLine->setUnitDir(vt);
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
void getLineByDbText(AcDbObjectId id, AcDbLine *pLine)
|
||
{
|
||
AcDbExtents ext;
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pText)
|
||
if (!pText) return;
|
||
pText->getGeomExtents(ext);
|
||
OPENOBJ_END()
|
||
pLine->setStartPoint(ext.minPoint());
|
||
pLine->setEndPoint(ext.maxPoint());
|
||
}
|
||
|
||
CString getDbTextString(AcDbObjectId id)
|
||
{
|
||
CString s(_T(""));
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pText)
|
||
if (!pText) return s;
|
||
s = pText->textString();
|
||
OPENOBJ_END()
|
||
return s;
|
||
}
|
||
|
||
struct _com_pnt_psz_pr
|
||
{
|
||
_com_pnt_psz_pr(AcDbXline &line):xline(line){}
|
||
bool operator()(std::pair<AcGePoint3d, CString> &a, std::pair<AcGePoint3d, CString> &b)
|
||
{
|
||
double dA(.0), dB(.0);
|
||
xline.getParamAtPoint(a.first, dA);
|
||
xline.getParamAtPoint(b.first, dB);
|
||
return dA < dB;
|
||
}
|
||
AcDbXline &xline;
|
||
};
|
||
|
||
void reverseCurve(AcDbPolyline *pL)
|
||
{
|
||
if (!pL) return;
|
||
#if ARX > 17
|
||
pL->reverseCurve();
|
||
#else
|
||
|
||
AcGePoint2d pt1(AcGePoint2d::kOrigin), pt2(AcGePoint2d::kOrigin);
|
||
double dStart1(.0), dEnd1(.0), dBulge1(.0), dStart2(.0), dEnd2(.0), dBulge2(.0);
|
||
Adesk::Int32 vertexIdentifier1(0), vertexIdentifier2(0);
|
||
|
||
int len = pL->numVerts() / 2;
|
||
int s = 0, e = pL->numVerts() - 1;
|
||
for (; s < len; ++s, --e)
|
||
{
|
||
pL->getPointAt(s, pt1);
|
||
pL->getBulgeAt(s, dBulge1);
|
||
pL->getWidthsAt(s, dStart1, dEnd1);
|
||
#if ARX > 17
|
||
pL->getVertexIdentifierAt(s, vertexIdentifier1);
|
||
#endif
|
||
|
||
pL->getPointAt(e, pt2);
|
||
pL->getBulgeAt(e, dBulge2);
|
||
pL->getWidthsAt(e, dStart2, dEnd2);
|
||
#if ARX > 17
|
||
pL->getVertexIdentifierAt(e, vertexIdentifier2);
|
||
#endif
|
||
|
||
pL->setPointAt(s, pt2);
|
||
pL->setBulgeAt(s, dBulge2 * -1);
|
||
pL->setWidthsAt(s, dStart2, dEnd2);
|
||
#if ARX > 17
|
||
pL->setVertexIdentifierAt(s, vertexIdentifier2);
|
||
#endif
|
||
|
||
pL->setPointAt(e, pt1);
|
||
pL->setBulgeAt(e, dBulge1 * -1);
|
||
pL->setWidthsAt(e, dStart1, dEnd1);
|
||
#if ARX > 17
|
||
pL->setVertexIdentifierAt(e, vertexIdentifier1);
|
||
#endif
|
||
}
|
||
|
||
return;
|
||
#endif
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
AcDbText* makeSameText(AcDbObjectId id, LPCTSTR pszContent, const AcGePoint3d &pt)
|
||
{
|
||
AcDbText *p(NULL);
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pSrc)
|
||
if (!pSrc) return p;
|
||
p = (AcDbText *)pSrc->clone();
|
||
p->setTextString(pszContent);
|
||
AcDb::TextVertMode vmode = p->verticalMode();
|
||
AcDb::TextHorzMode hmode = p->horizontalMode();
|
||
if (vmode == AcDb::kTextBase || hmode == AcDb::kTextLeft)
|
||
p->setPosition(pt);
|
||
else
|
||
p->setAlignmentPoint(pt);
|
||
OPENOBJ_END()
|
||
return p;
|
||
}
|
||
|
||
bool Is3DPolylineNode(AcDbObjectId &id, const AcGePoint3d &pt)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDb3dPolyline, p)
|
||
if (!p) return false;
|
||
AcDbObjectIterator* pIt = p->vertexIterator();
|
||
if (!pIt) return false;
|
||
|
||
AcGePoint3d pt3D(AcGePoint3d::kOrigin);
|
||
for (pIt->start(); !pIt->done(); pIt->step())
|
||
{
|
||
AcDb3dPolylineVertex* pVtx(NULL);
|
||
if (Acad::eOk != p->openVertex(pVtx, pIt->objectId(), AcDb::kForRead)) continue;
|
||
pt3D = pVtx->position();
|
||
if (pt == pt3D)
|
||
return true;
|
||
}
|
||
DELETE_PTR(pIt);
|
||
OPENOBJ_END()
|
||
return false;
|
||
}
|
||
|
||
bool findPointByStake(AcDbObjectId &id, LPCTSTR psz, AcGePoint3d &pt)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDb3dPolyline, p)
|
||
if (!p) return false;
|
||
AcDbObjectIterator* pIt = p->vertexIterator();
|
||
if (!pIt) return false;
|
||
|
||
CString strValue(_T(""));
|
||
AecDbObjXDataMap xmap;
|
||
for (pIt->start(); !pIt->done(); pIt->step())
|
||
{
|
||
xmap.Empty();
|
||
AcDb3dPolylineVertex* pVtx(NULL);
|
||
if (Acad::eOk != p->openVertex(pVtx, pIt->objectId(), AcDb::kForRead)) continue;
|
||
if (!xmap.Read(pVtx, _T("PL3D_STAKENO"))) continue;
|
||
if (!xmap.GetAt(_T("stake"), strValue)) continue;
|
||
if (strValue.CompareNoCase(psz) == 0)
|
||
{
|
||
pt = pVtx->position();
|
||
return true;
|
||
}
|
||
}
|
||
DELETE_PTR(pIt);
|
||
OPENOBJ_END()
|
||
return false;
|
||
}
|
||
|
||
// 根据3DPolyline上的点 pt3D, 得到其在polyline上的投影点
|
||
AcGePoint3d get2DPtFromPolylineBy3DPt(const AcGePoint3d &pt3D, const AcDbPolyline &poly)
|
||
{
|
||
// 理论上,polyline是根据3dpolyline对xoy面投影得到的。所以pt2DOrig一定在polyline上
|
||
AcGePoint3d pt;
|
||
poly.getClosestPointTo(pt3D, AcGeVector3d::kZAxis, pt);
|
||
return pt;
|
||
}
|
||
|
||
// 根据polyline上的点ptOrig,得到一个3DPolyline上的点
|
||
AcGePoint3d get3DPtFrom3DPolyline(AcDbObjectId &id3D, const AcGePoint3d &ptOrig)
|
||
{
|
||
AcGePoint3d pt(AcGePoint3d::kOrigin);
|
||
OPENOBJ_BEGIN(id3D, AcDb::kForRead, AcDb3dPolyline, p)
|
||
if (!p) return AcGePoint3d::kOrigin;
|
||
p->getClosestPointTo(ptOrig, AcGeVector3d::kZAxis, pt);
|
||
OPENOBJ_END()
|
||
return pt;
|
||
}
|
||
|
||
void insertTo3DPolyline(AcDbObjectId &id, const AcGePoint3d &pt3D)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDb3dPolyline, p)
|
||
if (!p) return;
|
||
AcDbObjectId verID(AcDbObjectId::kNull), newID(AcDbObjectId::kNull);
|
||
Acad::ErrorStatus es;
|
||
|
||
AcDbObjectIterator* pIt = p->vertexIterator();
|
||
if (!pIt) return;
|
||
|
||
double insPara(.0), prePara(.0), para(.0);
|
||
p->getParamAtPoint(pt3D, insPara);
|
||
|
||
AcDb3dPolylineVertex *pInsVert(NULL), *pPreVert(NULL);
|
||
pInsVert = new AcDb3dPolylineVertex;
|
||
pInsVert->setPosition(pt3D);
|
||
|
||
AcGePoint3d pt(AcGePoint3d::kOrigin);
|
||
for (pIt->start(); !pIt->done(); pIt->step())
|
||
{
|
||
AcDb3dPolylineVertex* pVtx(NULL);
|
||
es = p->openVertex(pVtx, pIt->objectId(), AcDb::kForRead);
|
||
if (es != Acad::eOk) continue;
|
||
|
||
pt = pVtx->position();
|
||
p->getParamAtPoint(pt, para);
|
||
|
||
// 说明此节点已存在,跳过
|
||
if (para == insPara)
|
||
{
|
||
acutPrintf(_T("\n节点存在,跳过。"));
|
||
pPreVert = pVtx;
|
||
continue;
|
||
}
|
||
|
||
if (para > insPara)
|
||
{
|
||
verID = pVtx->objectId();
|
||
break;
|
||
}
|
||
pPreVert = pVtx;
|
||
}
|
||
es = p->insertVertexAt(newID, verID, pInsVert);
|
||
pInsVert->close();
|
||
DELETE_PTR(pIt);
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
void collectDbText(std::vector<AcDbObjectId> &vec)
|
||
{
|
||
ads_name ss, ent;
|
||
struct resbuf* pRb = acutBuildList(RTDXF0, _T("TEXT"), 0);
|
||
int nRes = acedSSGet(_T("A"), NULL, NULL, pRb, ss);
|
||
if (nRes != RTNORM)
|
||
{
|
||
acutPrintf(_T("\n没有发现桩号文字。"));
|
||
return;
|
||
}
|
||
AcDbObjectId id(AcDbObjectId::kNull);
|
||
Adesk::Int32 lLen = 0L;
|
||
acedSSLength(ss, &lLen);
|
||
AcString str;
|
||
for (long i = 0; i < lLen; i++)
|
||
{
|
||
if (acedSSName(ss, i, ent) != RTNORM) continue;
|
||
if (acdbGetObjectId(id, ent) != Acad::eOk) continue;
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pTxt)
|
||
if (!pTxt) continue;
|
||
OPENOBJ_BEGIN(pTxt->blockId(), AcDb::kForRead, AcDbBlockTableRecord, pRec)
|
||
if (pRec)
|
||
{
|
||
pRec->getName(str);
|
||
if (CString(ACDB_MODEL_SPACE).CompareNoCase(str) != 0) continue;
|
||
vec.push_back(id);
|
||
}
|
||
OPENOBJ_END()
|
||
OPENOBJ_END()
|
||
}
|
||
acedSSFree(ss);
|
||
}
|
||
|
||
void addStakeForRedLine(AcDbObjectId &idRed, AcDbObjectId &idText, const double &dist)
|
||
{
|
||
// 对各个参数的保护性判断,放在调用端
|
||
AcDbPolyline poly2d;
|
||
if (!poly3D2Poly2D(idRed, poly2d))
|
||
{
|
||
acutPrintf(_T("\n曲线转换失败。"));
|
||
return;
|
||
}
|
||
|
||
AcGePoint3d pt3DStart(AcGePoint3d::kOrigin), pt3DEnd(AcGePoint3d::kOrigin);
|
||
AcGePoint3d pt2DStart(AcGePoint3d::kOrigin), pt2DEnd(AcGePoint3d::kOrigin);
|
||
|
||
// 起始/线束 桩号字符串
|
||
CString strStart(_T("")), strEnd(_T(""));
|
||
|
||
// 桩号前缀
|
||
CString prefix(_T(""));
|
||
|
||
// 开始桩号上的字符串数值
|
||
double stakeStartValue(.0);
|
||
// 开始/结束 桩号的真实距离
|
||
double startDist(.0), endDist(.0);
|
||
|
||
OPENOBJ_BEGIN(idText, AcDb::kForRead, AcDbText, pTxt)
|
||
strStart = pTxt->textString();
|
||
OPENOBJ_END()
|
||
|
||
// 找到起始点
|
||
if (!findPointByStake(idRed, strStart, pt3DStart))
|
||
{
|
||
acutPrintf(_T("\n3DPolyline线并没有和%s桩号关联。"), strStart);
|
||
return;
|
||
}
|
||
|
||
if (!StakeTools::analyStakeString(strStart, stakeStartValue, &prefix))
|
||
{
|
||
acutPrintf(_T("\n桩号形式满足要求(例:K1+123)"));
|
||
return;
|
||
}
|
||
|
||
poly2d.getClosestPointTo(pt3DStart, pt2DStart);
|
||
poly2d.getDistAtPoint(pt2DStart, startDist);
|
||
|
||
AcGePoint3d pt2D, pt3D;
|
||
CString sStake(_T(""));
|
||
|
||
startDist += dist;
|
||
stakeStartValue += dist;
|
||
|
||
poly2d.getPointAtDist(startDist, pt2D);
|
||
pt3D = get3DPtFrom3DPolyline(idRed, pt2D);
|
||
if (Is3DPolylineNode(idRed, pt3D)) return;
|
||
|
||
sStake = StakeTools::generateStakeString(stakeStartValue, prefix);
|
||
AcDbText *p = makeSameText(idText, sStake, pt3D);
|
||
AddToModelSpace(p);
|
||
}
|
||
|
||
bool getIntersectPoint(AcDbObjectId &idText, AcDbObjectId &idPoly, AcGePoint3d &pt)
|
||
{
|
||
AcDbXline xline;
|
||
getXLineByDbText(idText, &xline);
|
||
AcGePoint3dArray pts;
|
||
OPENOBJ_BEGIN(idPoly, AcDb::kForRead, AcDbCurve, pPoly)
|
||
pPoly->intersectWith(&xline, AcDb::kOnBothOperands, AcGePlane::kXYPlane, pts);
|
||
if (pts.isEmpty())
|
||
{
|
||
acutPrintf(_T("\n文字方向延长线不与选中的polyline相交。"));
|
||
return false;
|
||
}
|
||
OPENOBJ_END();
|
||
pt = pts[0];
|
||
return !pts.isEmpty();
|
||
}
|
||
|
||
Acad::ErrorStatus getDistAtPoint(AcDbObjectId id, const AcGePoint3d &pt, double &dist)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbCurve, pPoly)
|
||
if (pPoly)
|
||
return pPoly->getDistAtPoint(pt, dist);
|
||
OPENOBJ_END();
|
||
return Acad::eInvalidInput;
|
||
}
|
||
|
||
Acad::ErrorStatus getPointAtDist(AcDbObjectId id, const double &dist, AcGePoint3d &pt)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbCurve, pPoly)
|
||
if (pPoly)
|
||
return pPoly->getPointAtDist(dist, pt);
|
||
OPENOBJ_END();
|
||
return Acad::eInvalidInput;
|
||
}
|
||
|
||
Acad::ErrorStatus getFirstDeriv(AcDbObjectId id, const AcGePoint3d &pt, AcGeVector3d &vt)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbCurve, pPoly)
|
||
if (pPoly)
|
||
return pPoly->getFirstDeriv(pt, vt);
|
||
OPENOBJ_END();
|
||
return Acad::eInvalidInput;
|
||
}
|
||
|
||
Acad::ErrorStatus getClosestPointTo(AcDbObjectId id, const AcGePoint3d &ptGive, AcGePoint3d &ptOn)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbCurve, pPoly)
|
||
if (pPoly)
|
||
return pPoly->getClosestPointTo(ptGive, ptOn);
|
||
OPENOBJ_END();
|
||
return Acad::eInvalidInput;
|
||
}
|
||
|
||
AcDbObjectId getCenterRoldLine(LPCTSTR pszPrompt, LPCTSTR pszFilter)
|
||
{
|
||
double dw = CKTCadUtility::GetPickBoxSize();
|
||
|
||
ads_point pt;
|
||
ads_name ss, ent;
|
||
|
||
int nRes = acedEntSel(pszPrompt, ent, pt);
|
||
if (nRes != RTNORM) return AcDbObjectId::kNull;
|
||
|
||
ads_point pt1, pt2;
|
||
pt1[0] = pt[0] - dw;
|
||
pt1[1] = pt[1] - dw;
|
||
pt1[2] = pt[2];
|
||
pt2[0] = pt[0] + dw;
|
||
pt2[1] = pt[1] + dw;
|
||
pt2[2] = pt[2];
|
||
|
||
struct resbuf* pRb = acutBuildList(RTDXF0, pszFilter, 0);
|
||
nRes = acedSSGet(_T("C"), pt1, pt2, NULL, ss);
|
||
acutRelRb(pRb);
|
||
Adesk::Int32 len(0);
|
||
acedSSLength(ss, &len);
|
||
AcDbObjectId id(AcDbObjectId::kNull);
|
||
for (long i = 0; i < len; ++i)
|
||
{
|
||
if (acedSSName(ss, i, ent) != RTNORM) continue;
|
||
if (acdbGetObjectId(id, ent) != Acad::eOk) continue;
|
||
if (GLTools::isThisClass<AcDbPolyline>(id))
|
||
return id;
|
||
if (GLTools::isThisClass<AcDbLine>(id))
|
||
return id;
|
||
if (GLTools::isThisClass<AcDbArc>(id))
|
||
return id;
|
||
id == AcDbObjectId::kNull;
|
||
continue;
|
||
}
|
||
acedSSFree(ss);
|
||
|
||
return id;
|
||
}
|
||
|
||
bool getAllStake(std::map<double, AcDbObjectId, GLTools::compare_double> &stakes)
|
||
{
|
||
assert(false);
|
||
stakes.clear();
|
||
ads_name ss, ent;
|
||
struct resbuf* pRb = acutBuildList(RTDXF0, _T("TEXT"), 0);
|
||
int nRes = acedSSGet(_T("A"), NULL, NULL, pRb, ss);
|
||
if (nRes != RTNORM) return false;
|
||
|
||
Adesk::Int32 lLen(0L);
|
||
acedSSLength(ss, &lLen);
|
||
AcString str;
|
||
CString sTxt(_T(""));
|
||
double dist(.0);
|
||
AcDbObjectId id;
|
||
for (long i = 0; i < lLen; i++)
|
||
{
|
||
if (acedSSName(ss, i, ent) != RTNORM) continue;
|
||
if (acdbGetObjectId(id, ent) != Acad::eOk) continue;
|
||
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pTxt)
|
||
if (!pTxt) continue;
|
||
OPENOBJ_BEGIN(pTxt->blockId(), AcDb::kForRead, AcDbBlockTableRecord, pRec)
|
||
if (pRec)
|
||
{
|
||
pRec->getName(str);
|
||
if (CString(ACDB_MODEL_SPACE).CompareNoCase(str) != 0) continue;
|
||
}
|
||
OPENOBJ_END()
|
||
sTxt = pTxt->textString();
|
||
if (!StakeTools::analyStakeString(sTxt, dist)) continue;
|
||
stakes.insert(std::make_pair(dist, id));
|
||
OPENOBJ_END()
|
||
}
|
||
acedSSFree(ss);
|
||
|
||
return !stakes.empty();
|
||
}
|
||
|
||
bool getSHSStake(LPCTSTR pszPrompt
|
||
,AcDbObjectId &idTxt
|
||
, double &dist
|
||
, CString &prefix
|
||
, bool &bStart2End
|
||
, bool &bThousands
|
||
, AcGePoint3d *ptIns = NULL
|
||
, CString *orignString = NULL )
|
||
{
|
||
return StakeTools::getSHSStake(pszPrompt, idTxt, dist, prefix, bStart2End, bThousands, ptIns, orignString);
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
typedef std::map<double, double, GLTools::compare_double> D2DMap;
|
||
|
||
void drawCircle(const AcGePoint3d &pt, const double &r = 10)
|
||
{
|
||
AcDbCircle *p = new AcDbCircle(pt, AcGeVector3d::kZAxis, r);
|
||
AddToModelSpace(p);
|
||
}
|
||
|
||
// 解析高程文件
|
||
void analyElevationFile(LPCTSTR pszFile, D2DMap &mapStake)
|
||
{
|
||
if (!pszFile) return;
|
||
if (_taccess(pszFile, 0x0) != 0x0) return;
|
||
|
||
CStdioFile file(pszFile, CFile::shareDenyRead);
|
||
CString strLine(_T("")), sStake(_T("")), sElev(_T(""));
|
||
std::vector<CString> vecs;
|
||
double dDist(.0), dElev(.0);
|
||
CString prefix(_T("K"));
|
||
while (file.ReadString(strLine))
|
||
{
|
||
split(strLine, _T(' '), vecs);
|
||
|
||
if (vecs.size() != 2)
|
||
{
|
||
vecs.clear();
|
||
split(strLine, _T(','), vecs);
|
||
if (vecs.size() != 2)
|
||
continue;
|
||
}
|
||
|
||
sStake = vecs[0];
|
||
sElev = vecs[1];
|
||
|
||
if (!StakeTools::IsDoubleString(sElev)) continue;
|
||
|
||
dElev = _convert_<double, string>((LPCTSTR)sElev);
|
||
|
||
// 直接就是桩号距离
|
||
if (StakeTools::IsDoubleString(sStake))
|
||
dDist = _convert_<double, string>((LPCTSTR)sStake);
|
||
else if (StakeTools::analyStakeString(sStake, dDist, &prefix))
|
||
{
|
||
// 空
|
||
}
|
||
else
|
||
continue;
|
||
|
||
mapStake.insert(std::make_pair(dDist, dElev));
|
||
}
|
||
file.Close();
|
||
}
|
||
|
||
// 根据桩号文字的距离,得到其高程
|
||
bool getElevationByStakeDist(const double &dist, const D2DMap &mapStake, double &elev)
|
||
{
|
||
D2DMap::const_iterator it = mapStake.find(dist);
|
||
if (it != mapStake.end())
|
||
{
|
||
elev = it->second;
|
||
return true;
|
||
}
|
||
|
||
// 如果 dist 不在集合中,则取出其前后两个高程,
|
||
D2DMap::const_iterator itLeft(mapStake.begin()), itRight(mapStake.end());
|
||
for (D2DMap::const_iterator it = mapStake.begin(); it != mapStake.end(); ++it)
|
||
{
|
||
itRight = it;
|
||
if (it->first > dist)
|
||
{
|
||
if (it == mapStake.begin())
|
||
return false;
|
||
itLeft = --it;
|
||
// 根据前后两个高程,计算出真实高程
|
||
elev = ((itRight->first - itLeft->first) - (dist - itLeft->first))
|
||
* (abs(itRight->second - itLeft->second) / (itRight->first - itLeft->first))
|
||
+ __min(itRight->second, itLeft->second);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void makeSameDir(AcDbObjectId &polyId, AcDbObjectId ¢erId)
|
||
{
|
||
OPENOBJ_BEGIN(centerId, AcDb::kForRead, AcDbPolyline, pCenter)
|
||
if (!pCenter) return;
|
||
OPENOBJ_BEGIN(polyId, AcDb::kForWrite, AcDbPolyline, pPoly)
|
||
if (!pPoly) return;
|
||
AcGePoint3d ptCenterStart(AcGePoint3d::kOrigin), ptCenterEnd(AcGePoint3d::kOrigin);
|
||
AcGePoint3d ptPolyStart(AcGePoint3d::kOrigin), ptPolyEnd(AcGePoint3d::kOrigin);
|
||
pCenter->getStartPoint(ptCenterStart);
|
||
pCenter->getEndPoint(ptCenterEnd);
|
||
pPoly->getStartPoint(ptPolyStart);
|
||
pPoly->getEndPoint(ptPolyEnd);
|
||
AcGeVector3d vtCenter(ptCenterEnd - ptCenterStart);
|
||
AcGeVector3d vtPoly(ptPolyEnd - ptPolyStart);
|
||
if (vtCenter.dotProduct(vtPoly) >= 0) return;
|
||
acutPrintf(_T("\n选中的polyline与道路中心线方向相反。进行反转。"));
|
||
// 将 polylid 反向
|
||
#if ARX > 17
|
||
pPoly->reverseCurve();
|
||
#else
|
||
reverseCurve(pPoly);
|
||
#endif
|
||
OPENOBJ_END()
|
||
OPENOBJ_END()
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
struct STakeInfo
|
||
{
|
||
bool init(AcDbObjectId idText, const std::map<double, double, GLTools::compare_double> &dmap)
|
||
{
|
||
AcString str;
|
||
CString sTxt;
|
||
AcGePoint3d ptTxt;
|
||
OPENOBJ_BEGIN(idText, AcDb::kForRead, AcDbText, pTxt)
|
||
if (!pTxt) return false;
|
||
OPENOBJ_BEGIN(pTxt->blockId(), AcDb::kForRead, AcDbBlockTableRecord, pRec)
|
||
if (pRec)
|
||
{
|
||
pRec->getName(str);
|
||
if (CString(ACDB_MODEL_SPACE).CompareNoCase(str) != 0) return false;
|
||
}
|
||
id = idText;
|
||
OPENOBJ_END()
|
||
sTxt = pTxt->textString();
|
||
if (!StakeTools::analyStakeString(sTxt, dist)) return false;
|
||
stake = sTxt;
|
||
std::map<double, double, GLTools::compare_double>::const_iterator it = dmap.find(dist);
|
||
if (it == dmap.end()) return false;
|
||
elev = it->second;
|
||
OPENOBJ_END()
|
||
return true;
|
||
}
|
||
|
||
struct compare_dist{ bool operator () (const STakeInfo &a, const STakeInfo &b) const { return a.dist < b.dist; } };
|
||
|
||
AcDbObjectId id;
|
||
CString stake;
|
||
double dist;
|
||
double elev;
|
||
};
|
||
|
||
}
|
||
|
||
namespace
|
||
{
|
||
void mergeWithLeft(AecDbEarthWorm *pEw, AecDbEarthWorm *pLeft, bool bModifyStartElev)
|
||
{
|
||
pLeft->SetNextDir(pEw->GetHeadDir());
|
||
pEw->SetLastDir(pLeft->GetTailDir());
|
||
if (bModifyStartElev)
|
||
pEw->SetStartElevation(pLeft->EndElevation(), false);
|
||
}
|
||
void mergeWithLeft(AecDbEarthWorm *pEw, AcDbObjectId idLeft, bool bModifyStartElev)
|
||
{
|
||
OPENOBJ_BEGIN(idLeft, AcDb::kForWrite, AecDbEarthWorm, pLeft)
|
||
if (!pLeft) return;
|
||
mergeWithLeft(pEw, pLeft, bModifyStartElev);
|
||
OPENOBJ_END()
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
AcDbObjectId searchSHStakeByString(const std::vector<AcDbObjectId> &ids, LPCTSTR psz, AcDbObjectId &leftId)
|
||
{
|
||
AcDbObjectId id(AcDbObjectId::kNull);
|
||
if (!psz || ids.empty()) return id;
|
||
|
||
double dDist(.0), dDistTxt(.0);
|
||
if (!StakeTools::analyStakeString(psz, dDist)) return id;
|
||
|
||
for (size_t i = 0; i < ids.size(); ++i)
|
||
{
|
||
id = ids[i];
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, p)
|
||
if (!p) continue;
|
||
StakeTools::analyStakeString(p->textString(), dDistTxt);
|
||
if (EQUAL(dDistTxt, dDist)) break;
|
||
if (UP_ZERO(dDistTxt - dDist))
|
||
{
|
||
if (i != 0)
|
||
leftId = ids[i - 1];
|
||
id = AcDbObjectId::kNull;
|
||
break;
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
return id;
|
||
}
|
||
|
||
void getRay(AcDbObjectId &id, AcDbRay &ray, const double &dAngle)
|
||
{
|
||
OPENOBJ_BEGIN(id, AcDb::kForWrite, AecDbEarthWorm, pEw)
|
||
AcGePoint2d pt2dS(AcGePoint2d::kOrigin), pt2dE(AcGePoint2d::kOrigin);
|
||
pt2dS = pEw->StartPoint();
|
||
pt2dE = pEw->EndPoint();
|
||
AcGeVector3d vt3d = AcGePoint3d(pt2dE.x, pt2dE.y, .0) - AcGePoint3d(pt2dS.x, pt2dS.y, .0);
|
||
vt3d.rotateBy(dAngle, AcGeVector3d::kZAxis);
|
||
ray.setBasePoint(AcGePoint3d(pt2dS.x, pt2dS.y, .0));
|
||
ray.setUnitDir(vt3d);
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
void getXline(AcDbObjectId &idTxt, AcDbObjectId &idLeftTxt, AcDbXline &xline, AcDbObjectId &idPoly, LPCTSTR stake)
|
||
{
|
||
double dRot(.0);
|
||
AcGePoint3d ptBase(AcGePoint3d::kOrigin);
|
||
AcGeVector3d vtBase(AcGeVector3d::kXAxis);
|
||
if (idTxt.isValid())
|
||
{
|
||
OPENOBJ_BEGIN(idTxt, AcDb::kForRead, AcDbText, pTxt)
|
||
if (!pTxt)
|
||
{
|
||
acutPrintf(_T("\n搜索出的桩号出现问题。"));
|
||
return;
|
||
}
|
||
dRot = pTxt->rotation();
|
||
ptBase = pTxt->alignmentPoint();
|
||
vtBase.rotateBy(dRot, AcGeVector3d::kZAxis);
|
||
OPENOBJ_END()
|
||
}
|
||
else
|
||
{
|
||
if (!idLeftTxt.isValid())
|
||
{
|
||
acutPrintf(_T("\nidLeftText无效。"));
|
||
return;
|
||
}
|
||
|
||
double dLeft(.0), d(.0);
|
||
AcGeVector3d vtOld(AcGeVector3d::kXAxis);
|
||
OPENOBJ_BEGIN(idLeftTxt, AcDb::kForRead, AcDbText, pTxt)
|
||
if (!pTxt)
|
||
{
|
||
acutPrintf(_T("\n搜索出的桩号出现问题。"));
|
||
return;
|
||
}
|
||
StakeTools::analyStakeString(pTxt->textString(), dLeft);
|
||
vtOld.rotateBy(pTxt->rotation(), AcGeVector3d::kZAxis);
|
||
OPENOBJ_END()
|
||
|
||
StakeTools::analyStakeString(stake, d);
|
||
double delta(d - dLeft);
|
||
|
||
AcGePoint3d ptInsLeft(AcGePoint3d::kOrigin), ptInsNew(AcGePoint3d::kOrigin);
|
||
bool b;
|
||
CString s;
|
||
StakeTools::readSHSStake(idLeftTxt, ptInsLeft, b, s, d, d);
|
||
getDistAtPoint(idPoly, ptInsLeft, d);
|
||
getPointAtDist(idPoly, d + delta, ptBase);
|
||
getFirstDeriv(idPoly, ptBase, vtBase);
|
||
|
||
vtBase.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
if (vtBase.dotProduct(vtOld) < 0)
|
||
vtBase.rotateBy(PI, AcGeVector3d::kZAxis);
|
||
}
|
||
xline.setBasePoint(ptBase);
|
||
xline.setUnitDir(vtBase);
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
void GiDrawPipeTest()
|
||
{
|
||
AcDbEntity *p(NULL);
|
||
ads_name adsEnt;
|
||
ads_point adsPt;
|
||
int rt;
|
||
TCHAR szKey[131] = {};
|
||
acedInitGet(RSG_OTHER, _T("1 2 3"));
|
||
rt = acedGetKword(_T("\n请选择[通过半径壁厚绘制(1)/通过闭合polyline做为截面绘制(2)/通过region做为截面绘制(3)]<通过半径壁厚绘制(1)>:"), szKey);
|
||
if (rt == RTNONE) _tcscpy(szKey, _T("1"));
|
||
else if (rt == RTCAN) return;
|
||
|
||
if (_tcscmp(szKey, _T("1")) == 0)
|
||
{
|
||
double dR(100), dT(10);
|
||
rt = acedGetReal(_T("\n请输入管线半径<100>:"), &dR);
|
||
rt = acedGetReal(_T("\n请输入管线厚度<10>:"), &dT);
|
||
rt = acedGetPoint(NULL, _T("\n请选择起点:"), adsPt);
|
||
ads_point adsPt1;
|
||
acdbUcs2Wcs(adsPt, adsPt1, false);
|
||
if (rt != RTNORM) return;
|
||
AcGePoint3d ptS(asPnt3d(adsPt1));
|
||
rt = acedGetPoint(adsPt, _T("\n请选择终点:"), adsPt);
|
||
acdbUcs2Wcs(adsPt, adsPt1, false);
|
||
if (rt != RTNORM) return;
|
||
AcGePoint3d ptE(asPnt3d(adsPt1));
|
||
p = GiDrawUtility::DrawPipe(ptS, ptE, dR, dT);
|
||
AddToModelSpace(p);
|
||
return;
|
||
}
|
||
rt = acedEntSel(_T("\n选择一段曲线做为管线路径:"), adsEnt, adsPt);
|
||
if (rt != RTNORM) return;
|
||
|
||
|
||
AcDbObjectId id;
|
||
acdbGetObjectId(id, adsEnt);
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbCurve, pPath)
|
||
if (!pPath)
|
||
{
|
||
acutPrintf(_T("\n所选实体不是曲线。"));
|
||
return;
|
||
}
|
||
if (_tcscmp(szKey, _T("2")) == 0)
|
||
{
|
||
rt = acedEntSel(_T("\n请选择一个闭合的polyline做为管线截面:"), adsEnt, adsPt);
|
||
if (rt != RTNORM) return;
|
||
AcDbObjectId idSection;
|
||
acdbGetObjectId(idSection, adsEnt);
|
||
OPENOBJ_BEGIN(idSection, AcDb::kForRead, AcDbPolyline, pSection)
|
||
if (!pSection)
|
||
{
|
||
acutPrintf(_T("\n所选实体不是polyline。"));
|
||
return;
|
||
}
|
||
AcDbExtents ext;
|
||
pSection->getGeomExtents(ext);
|
||
AcGePoint3d ptOn((ext.maxPoint().x + ext.minPoint().x) * .5, (ext.maxPoint().y + ext.minPoint().y) * .5, (ext.maxPoint().z + ext.minPoint().z) * .5);
|
||
p = GiDrawUtility::DrawPipe(pPath, pSection, ptOn);
|
||
if (p) AddToModelSpace(p);
|
||
OPENOBJ_END()
|
||
}
|
||
else
|
||
{
|
||
rt = acedEntSel(_T("\n请选择一个region做为管线截面:"), adsEnt, adsPt);
|
||
if (rt != RTNORM) return;
|
||
AcDbObjectId idSection;
|
||
acdbGetObjectId(idSection, adsEnt);
|
||
OPENOBJ_BEGIN(idSection, AcDb::kForRead, AcDbRegion, pSection)
|
||
if (!pSection)
|
||
{
|
||
acutPrintf(_T("\n所选实体不是region。"));
|
||
return;
|
||
}
|
||
AcDbExtents ext;
|
||
pSection->getGeomExtents(ext);
|
||
AcGePoint3d ptOn((ext.maxPoint().x + ext.minPoint().x) * .5, (ext.maxPoint().y + ext.minPoint().y) * .5, (ext.maxPoint().z + ext.minPoint().z) * .5);
|
||
p = GiDrawUtility::DrawPipe(pPath, pSection, ptOn);
|
||
if (p) AddToModelSpace(p);
|
||
OPENOBJ_END()
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
}
|
||
|
||
namespace
|
||
{
|
||
bool insertVertexForPolyline(AcDbPolyline *pPoly, const AcGePoint3d &pt)
|
||
{
|
||
if (!pPoly) return false;
|
||
if (pPoly->numVerts() <= 2) return false;
|
||
|
||
AcGePoint2d pt1, pt2, pt2D(pt.x, pt.y);
|
||
double dist, dist1(.0), dist2(.0);
|
||
pPoly->getDistAtPoint(pt, dist);
|
||
|
||
// 判断在哪个seg上
|
||
double bulge, r;
|
||
AcGeCircArc2d arc;
|
||
int negative(1);
|
||
for (int i = 0; i < pPoly->numVerts() - 1; i++)
|
||
{
|
||
pPoly->getPointAt(i, pt1);
|
||
pPoly->getPointAt(i + 1, pt2);
|
||
pPoly->getBulgeAt(i, bulge);
|
||
pPoly->getDistAtPoint(AcGePoint3d(pt1.x, pt1.y, 0.), dist1);
|
||
pPoly->getDistAtPoint(AcGePoint3d(pt2.x, pt2.y, 0.), dist2);
|
||
|
||
// 判断是否在两个端点上,如果是,走人
|
||
if (pt2D.distanceTo(pt1) < 1e-7) return true;
|
||
if (pt2D.distanceTo(pt2) < 1e-7) return true;
|
||
|
||
// 不在pt1,pt2内,走人
|
||
if (dist < dist1 || dist > dist2) continue;
|
||
|
||
if (abs(bulge) < 1e-7) // 直线
|
||
{
|
||
pPoly->addVertexAt(i+1, pt2D);
|
||
}
|
||
else // 弧线
|
||
{
|
||
negative = bulge > 0 ? 1 : -1;
|
||
pPoly->getArcSegAt(i, arc);
|
||
r = arc.radius();
|
||
pPoly->setBulgeAt(i, tan((dist - dist1) / r * .25) * negative);
|
||
pPoly->addVertexAt(i+1, pt2D, tan((dist2 - dist) / r * .25) * negative);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 取出 vertex1和vertex2之间的曲线,vertex1,vertex2为节点
|
||
AcDbPolyline* cutPolyline(AcDbPolyline* pPoly, AcGePoint3d &vertex1, AcGePoint3d &vertex2)
|
||
{
|
||
if (!pPoly) return NULL;
|
||
|
||
double d(.0), d1(.0), d2(.0);
|
||
pPoly->getDistAtPoint(vertex1, d1);
|
||
pPoly->getDistAtPoint(vertex2, d2);
|
||
if (d1 > d2)
|
||
{
|
||
AcGePoint3d pt(vertex1);
|
||
vertex1 = vertex2;
|
||
vertex2 = pt;
|
||
pPoly->getDistAtPoint(vertex1, d1);
|
||
pPoly->getDistAtPoint(vertex2, d2);
|
||
}
|
||
|
||
AcGePoint2d pt(AcGePoint2d::kOrigin)
|
||
, pt1(vertex1.x, vertex1.y)
|
||
, pt2(vertex2.x, vertex2.y);
|
||
int idx1(-1), idx2(-1);
|
||
for (int i = 0; i < pPoly->numVerts(); i++)
|
||
{
|
||
pPoly->getPointAt(i, pt);
|
||
if (pt.distanceTo(pt1) <= 1e-7)
|
||
idx1 = i;
|
||
if (pt.distanceTo(pt2) <= 1e-7)
|
||
idx2 = i;
|
||
}
|
||
|
||
AcDbPolyline *p = new AcDbPolyline();
|
||
for (int i = idx1, v=0; i <= idx2; ++i, ++v)
|
||
{
|
||
pPoly->getPointAt(i, pt);
|
||
pPoly->getBulgeAt(i, d);
|
||
p->addVertexAt(v, pt, d);
|
||
}
|
||
|
||
return p;
|
||
}
|
||
|
||
AcDbPolyline* MergePolyline(AcDbPolyline *pPoly)
|
||
{
|
||
if (!pPoly) return NULL;
|
||
|
||
AcDbPolyline *pClone = (AcDbPolyline*)pPoly->clone();
|
||
|
||
if (pPoly->numVerts() <= 2) return pClone;
|
||
|
||
AcGePoint2d pt;
|
||
AcGeLineSeg2d seg1, seg2;
|
||
double bulge1(.0), bulge2(.0);
|
||
AcGeVector2d v1, v2;
|
||
for (int i = 0; i < pClone->numVerts() - 2; ++i)
|
||
{
|
||
pClone->getBulgeAt(i, bulge1);
|
||
pClone->getBulgeAt(i + 1, bulge2);
|
||
pClone->getPointAt(i + 1, pt);
|
||
|
||
if (abs(bulge1) < 1e-7 && abs(bulge2) < 1e-7) // 第1段与2段都是直线
|
||
{
|
||
pClone->getLineSegAt(i, seg1);
|
||
pClone->getLineSegAt(i + 1, seg2);
|
||
v1 = seg1.direction();
|
||
v2 = seg2.direction();
|
||
if (seg1.direction() == seg2.direction()) // 方向且相同,则去掉中间的vertex
|
||
{
|
||
pClone->removeVertexAt(i + 1);
|
||
i = -1;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
return pClone;
|
||
}
|
||
}
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
namespace StakeOper
|
||
{
|
||
struct STBgs
|
||
{
|
||
// 桩号总距离,标高,曲率半径, 与上一个桩号的距离差
|
||
double distance, elevation, radius, subDistance;
|
||
};
|
||
|
||
// 取与dist最近的左右两个gbs点
|
||
void findClosed(const std::vector<STBgs> &vec, const double &dist, STBgs &big, STBgs &smal)
|
||
{
|
||
for (size_t i = 0; i < vec.size(); ++i)
|
||
{
|
||
const STBgs &bgs = vec[i];
|
||
if (bgs.distance > dist)
|
||
{
|
||
big = bgs;
|
||
if (i - 1 < 0)
|
||
{
|
||
acutPrintf(_T("\nfindClosed出现越界,请检查。"));
|
||
return;
|
||
}
|
||
smal = vec[i - 1];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void offsetEWLine(AcDbObjectId id, double dOffset)
|
||
{
|
||
ads_point pt1, pt2;
|
||
AcGePoint3d ptFirst(AcGePoint3d::kOrigin);
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDb3dPolyline, pPoly)
|
||
if (!pPoly) return;
|
||
double len;
|
||
pPoly->getEndParam(len);
|
||
pPoly->getPointAtDist(len * .5, ptFirst);
|
||
OPENOBJ_END()
|
||
ptFirst.z = 0.;
|
||
acdbWcs2Ucs(asDblArray(ptFirst), pt2, false);
|
||
acedGetPoint(pt2, _T("\n请指定要偏移的那一侧上的点:"), pt1);
|
||
|
||
ads_point pt0, pt11;
|
||
acdbUcs2Wcs(pt2, pt0, false);
|
||
acdbUcs2Wcs(pt1, pt11, false);
|
||
AcGeVector3d vtDir = asPnt3d(pt11) - asPnt3d(pt0);
|
||
AcDbRay ray;
|
||
ray.setBasePoint(asPnt3d(pt0));
|
||
ray.setUnitDir(vtDir);
|
||
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDb3dPolyline, pPoly)
|
||
if (!pPoly) return;
|
||
AcGePoint3d ptGe;
|
||
AcGePoint3dArray pts;
|
||
CStringArray stakes;
|
||
CString strValue;
|
||
|
||
AcDbObjectIterator* pIt = pPoly->vertexIterator();
|
||
if (!pIt) return;
|
||
for (pIt->start(); !pIt->done(); pIt->step())
|
||
{
|
||
AcDb3dPolylineVertex* pVtx = NULL;
|
||
if (Acad::eOk == pPoly->openVertex(pVtx, pIt->objectId(), AcDb::kForRead))
|
||
{
|
||
AecDbObjXDataMap xmap;
|
||
if (xmap.Read(pVtx, _T("PL3D_STAKENO")));
|
||
{
|
||
ptGe = pVtx->position();
|
||
if (xmap.GetAt(_T("stake"), strValue))
|
||
{
|
||
pts.append(ptGe);
|
||
stakes.Add(strValue);
|
||
}
|
||
}
|
||
pVtx->close();
|
||
}
|
||
}
|
||
DELETE_PTR(pIt);
|
||
|
||
if (stakes.IsEmpty())
|
||
{
|
||
acutPrintf(_T("\n选择的实体没有道路中心线信息!"));
|
||
}
|
||
|
||
//点投影到xy面
|
||
AcDbPolyline* pPl = new AcDbPolyline;
|
||
pPl->setNormal(AcGeVector3d::kZAxis);
|
||
pPl->setElevation(0.0);
|
||
for (int i = 0; i < pts.length(); i++)
|
||
{
|
||
pPl->addVertexAt(i, pts.at(i).convert2d(AcGePlane::kXYPlane));
|
||
}
|
||
|
||
AcDbPolyline* pPlOffset = NULL;
|
||
|
||
Acad::ErrorStatus es;
|
||
//提取偏移线-------------------------------------------------------------------
|
||
AcDbVoidPtrArray arPlPtr1;
|
||
es = pPl->getOffsetCurves(dOffset, arPlPtr1);
|
||
|
||
if (arPlPtr1.length() == 1)
|
||
{
|
||
AcDbPolyline* pPlOffset1 = (AcDbPolyline*)arPlPtr1.first();
|
||
|
||
AcGePoint3dArray arPoints1;
|
||
es = pPlOffset1->intersectWith(&ray, AcDb::kOnBothOperands, arPoints1);
|
||
|
||
if (!arPoints1.isEmpty())
|
||
{
|
||
pPlOffset = pPlOffset1;
|
||
}
|
||
else
|
||
{
|
||
DELETE_PTR(pPlOffset1);
|
||
}
|
||
}
|
||
|
||
AcDbVoidPtrArray arPlPtr2;
|
||
es = pPl->getOffsetCurves(-dOffset, arPlPtr2);
|
||
if (arPlPtr2.length() == 1)
|
||
{
|
||
AcDbPolyline* pPlOffset2 = (AcDbPolyline*)arPlPtr2.first();
|
||
|
||
AcGePoint3dArray arPoints2;
|
||
pPlOffset2->intersectWith(&ray, AcDb::kOnBothOperands, arPoints2);
|
||
|
||
if (!arPoints2.isEmpty())
|
||
{
|
||
pPlOffset = pPlOffset2;
|
||
}
|
||
else
|
||
{
|
||
DELETE_PTR(pPlOffset2);
|
||
}
|
||
}
|
||
|
||
DELETE_PTR(pPl);
|
||
|
||
//合成新的3dpolyline ----------------------------------------------------------
|
||
if (pPlOffset != NULL)
|
||
{
|
||
AcDb3dPolyline* p3dpL = new AcDb3dPolyline;
|
||
p3dpL->setColorIndex(1);
|
||
|
||
AcGePoint3d ptGe;
|
||
for (int i = 0; i < pPlOffset->numVerts(); i++)
|
||
{
|
||
pPlOffset->getPointAt(i, ptGe);
|
||
if (i < pts.length())
|
||
{
|
||
ptGe.z = pts.at(i).z;
|
||
}
|
||
|
||
AecDbObjXDataMap xmap;
|
||
AcDb3dPolylineVertex *pVer = new AcDb3dPolylineVertex;
|
||
pVer->setPosition(ptGe);
|
||
xmap.SetAt(_T("stake"), stakes.GetAt(i));
|
||
xmap.Write(pVer, _T("PL3D_STAKENO"));
|
||
p3dpL->appendVertex(pVer);
|
||
}
|
||
AddToModelSpace(p3dpL, NULL, true);
|
||
DELETE_PTR(pPlOffset);
|
||
}
|
||
else
|
||
{
|
||
acutPrintf(_T("\n偏移道路中心线失败 (ERROR:%d)!"), es);
|
||
return;
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
// 解析 bgs 文件
|
||
bool analyBGSFile(LPCTSTR szPath, std::vector<STBgs> &bgss)
|
||
{
|
||
if (_taccess(szPath, 0x0) != 0x0) return false;
|
||
CStdioFile file(szPath, CFile::shareDenyRead);
|
||
if (!file.m_hFile) return false;
|
||
|
||
CString strLine(_T(""));
|
||
std::vector<CString> vecs;
|
||
STBgs bgs = {.0, .0, .0};
|
||
while (file.ReadString(strLine))
|
||
{
|
||
strLine.Trim(_T('('));
|
||
strLine.Trim(_T(')'));
|
||
split(strLine, _T(' '), vecs);
|
||
if (vecs.size() < 2)
|
||
{
|
||
split(strLine, _T(','), vecs);
|
||
if (vecs.size() < 2) continue;
|
||
}
|
||
|
||
if (!StakeTools::analyStakeString(vecs[0], bgs.distance))
|
||
{
|
||
if (StakeTools::IsDoubleString(vecs[0]))
|
||
bgs.distance = _ttof(vecs[0]);
|
||
else
|
||
continue;
|
||
}
|
||
|
||
bgs.elevation = _ttof(vecs[1]);
|
||
if (vecs.size() > 2)
|
||
bgs.radius = _ttof(vecs[2]);
|
||
bgss.push_back(bgs);
|
||
}
|
||
if (!bgss.empty())
|
||
bgss[0].subDistance = bgss[0].distance;
|
||
for (size_t i = 1; i < bgss.size(); ++i)
|
||
{
|
||
STBgs &bgs0 = bgss[i - 1];
|
||
STBgs &bgs1 = bgss[i];
|
||
bgs1.subDistance = bgs1.distance - bgs0.distance;
|
||
}
|
||
|
||
file.Close();
|
||
return true;
|
||
}
|
||
|
||
// 生成参照曲线
|
||
void generateReferenceCurve()
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 生成管廊红线
|
||
void generateEWLine()
|
||
{
|
||
ads_name adsName;
|
||
ads_point adsPnt;
|
||
|
||
double dSpace(20.)
|
||
, dOffset(50.)
|
||
, dStartDist(.0)
|
||
, dEndDist(.0);
|
||
|
||
AcDbObjectId refCurveID(AcDbObjectId::kNull)
|
||
, StartTxtID(AcDbObjectId::kNull)
|
||
, EndTxtID(AcDbObjectId::kNull);
|
||
|
||
CString strPrefix(_T("")), str(_T(""));
|
||
|
||
int nRes = acedEntSel(_T("\n请选择参照曲线:"), adsName, adsPnt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(refCurveID, adsName);
|
||
if (!GLTools::isThisClass<AecDb3dRoadAxisLine>(refCurveID))
|
||
{
|
||
acutPrintf(_T("\n选择的实体不是参照曲线。"));
|
||
return;
|
||
}
|
||
|
||
nRes = acedEntSel(_T("\n请选择初始桩号<选择参照线起点>:"), adsName, adsPnt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(StartTxtID, adsName);
|
||
if (!GLTools::isThisClass<AcDbText>(StartTxtID))
|
||
{
|
||
acutPrintf(_T("\n请选择一个文字对象。"));
|
||
return;
|
||
}
|
||
|
||
nRes = acedEntSel(_T("\n请选择结束桩号<选择参照线终点>:"), adsName, adsPnt);
|
||
if (nRes == RTNORM) acdbGetObjectId(EndTxtID, adsName);
|
||
|
||
nRes = acedGetReal(_T("\n请输入两段桩号的间距<20>:"), &dSpace);
|
||
nRes = acedGetReal(_T("\n请输入与参照曲线的偏移距离<50>:"), &dOffset);
|
||
|
||
OPENOBJ_BEGIN(StartTxtID, AcDb::kForRead, AcDbText, p)
|
||
str = p->textString();
|
||
if (!StakeTools::analyStakeString(str, dStartDist, &strPrefix))
|
||
{
|
||
acutPrintf(_T("\n选择的桩号文字内容出错,请检查是否是\"K1+123\"形式。"));
|
||
return;
|
||
}
|
||
// 处理一下 dStartDist,取整
|
||
dStartDist = roundUpNum(dStartDist, 10);
|
||
OPENOBJ_END()
|
||
|
||
OPENOBJ_BEGIN(EndTxtID, AcDb::kForRead, AcDbText, p)
|
||
if (p)
|
||
{
|
||
str = p->textString();
|
||
if (!StakeTools::analyStakeString(str, dEndDist))
|
||
{
|
||
acutPrintf(_T("\n选择的桩号文字内容出错,请检查是否是\"K1+123\"形式。"));
|
||
return;
|
||
}
|
||
}
|
||
else // 取参考线总长
|
||
{
|
||
OPENOBJ_BEGIN(refCurveID, AcDb::kForRead, AecDb3dRoadAxisLine, pL)
|
||
pL->getEndParam(dEndDist);
|
||
OPENOBJ_END()
|
||
}
|
||
OPENOBJ_END()
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> pts(0);
|
||
double dist(dStartDist/* + dSpace*/);
|
||
AcGePoint3d pt;
|
||
OPENOBJ_BEGIN(refCurveID, AcDb::kForRead, AecDb3dRoadAxisLine, p)
|
||
while (dist < dEndDist)
|
||
{
|
||
p->getPointAtDist(dist, pt);
|
||
str = StakeTools::generateStakeString(dist);
|
||
pts.push_back(std::make_pair(pt, str));
|
||
AcDbText *pTxt = makeSameText(StartTxtID, str, pt);
|
||
pTxt->setPosition(pt);
|
||
AddToModelSpace(pTxt);
|
||
dist += dSpace;
|
||
}
|
||
|
||
AcDbObjectId redID = insert3dPoly(pts);
|
||
|
||
offsetEWLine(redID, dOffset);
|
||
|
||
OPENOBJ_BEGIN(redID, AcDb::kForWrite, AcDbEntity, pRd)
|
||
if (pRd) pRd->erase();
|
||
OPENOBJ_END()
|
||
|
||
if (AfxMessageBox(_T("是否输出管廊高程线文件?"), MB_YESNO) == IDYES)
|
||
{
|
||
outputTXTFile(pts, _T("管廊高程文件 (*.txt)|*.txt;*.txt||"));
|
||
}
|
||
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
// 提取整数桩号标高
|
||
void extractStakeElevation()
|
||
{
|
||
// 读取bgs文件
|
||
CString szFilter = _T("桩号数据 (*.txt;*.bgs;*.sqx)|*.txt;*.bgs;*.sqx|所有文件(*.*)|*.*||");
|
||
CFileDialog fileDlg(TRUE, _T("桩号数据"), NULL, OFN_HIDEREADONLY, szFilter, acedGetAcadFrame());
|
||
int nRes = fileDlg.DoModal();
|
||
if (nRes != IDOK) return;
|
||
|
||
CString strFile = fileDlg.GetPathName();
|
||
std::vector<STBgs> bgss(0);
|
||
if (!analyBGSFile(strFile, bgss))
|
||
{
|
||
acutPrintf(_T("\n解析文件%s出错,请检查文件。"), strFile);
|
||
return;
|
||
}
|
||
|
||
if (bgss.empty())
|
||
{
|
||
acutPrintf(_T("\n解析文件%s出错,请检查文件。"), strFile);
|
||
return;
|
||
}
|
||
|
||
// 弹出对话框,用户选择一个桩号,输入一段间距
|
||
CAcModuleResourceOverride myResources;
|
||
CTQBGDlg dlg(bgss.rbegin()->distance, bgss.begin()->distance);
|
||
if (dlg.DoModal() != IDOK)
|
||
return;
|
||
|
||
double start = dlg.getStart();
|
||
double end = dlg.getEnd();
|
||
|
||
double Space = dlg.getSpace(); // 间距
|
||
// 取出与selBgs最近的一个整数桩号(10的倍数)
|
||
//start = roundUpNum(start, 10);
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> pts(0);
|
||
STBgs big, smal;
|
||
double z(.0);
|
||
CString stake(_T(""));
|
||
while (start <= end)
|
||
{
|
||
// 找到与之最近的两个存在bgs桩号点,连直线,
|
||
// 沿起点移动start - bgs.distance 距离,
|
||
// 求出直线上的pt点,取其z值
|
||
findClosed(bgss, start, big, smal);
|
||
z = ((big.distance - smal.distance) - (start - smal.distance))
|
||
* (abs(big.elevation - smal.elevation) / (big.distance - smal.distance))
|
||
+ __min(big.elevation, smal.elevation);
|
||
stake = StakeTools::generateStakeString(start);
|
||
pts.push_back(std::make_pair(AcGePoint3d(0.,0.,z), stake));
|
||
start += Space;
|
||
}
|
||
// 放入最后一个
|
||
pts.push_back(std::make_pair(AcGePoint3d(0, 0, bgss.rbegin()->elevation), StakeTools::generateStakeString(bgss.rbegin()->distance)));
|
||
|
||
outputTXTFile(pts, _T("管廊高程文件 (*.txt)|*.txt||"));
|
||
}
|
||
|
||
// 提取图纸中的桩号及桩号对应的地面高程和设计高程
|
||
void extractElevationByDwg()
|
||
{
|
||
ads_point pt;
|
||
ads_name name_stake, name_ground, name_design;
|
||
AcDbObjectId idStake, idGround, idDesign;
|
||
|
||
int nRes = acedEntSel(_T("\n请选择“里程与桩号”所在行的行头。"), name_stake, pt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(idStake, name_stake);
|
||
if (!GLTools::isThisClass<AcDbText>(idStake))
|
||
{
|
||
acutPrintf(_T("\n请选择一个文字对象。"));
|
||
return;
|
||
}
|
||
|
||
nRes = acedEntSel(_T("\n请选择“地面高程”所在行的行头。"), name_ground, pt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(idGround, name_ground);
|
||
if (!GLTools::isThisClass<AcDbText>(idGround))
|
||
{
|
||
acutPrintf(_T("\n请选择一个文字对象。"));
|
||
return;
|
||
}
|
||
|
||
nRes = acedEntSel(_T("\n请选择“设计高程”所在行的行头。"), name_design, pt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(idDesign, name_design);
|
||
if (!GLTools::isThisClass<AcDbText>(idDesign))
|
||
{
|
||
acutPrintf(_T("\n请选择一个文字对象。"));
|
||
return;
|
||
}
|
||
|
||
// 收集所有模型空间内文字对象
|
||
std::vector<AcDbObjectId> ids(0);
|
||
collectDbText(ids);
|
||
|
||
// 去掉三个行头文字ID
|
||
std::vector<AcDbObjectId>::iterator it = std::find(ids.begin(), ids.end(), idStake);
|
||
if (it != ids.end()) ids.erase(it);
|
||
it = std::find(ids.begin(), ids.end(), idGround);
|
||
if (it != ids.end()) ids.erase(it);
|
||
it = std::find(ids.begin(), ids.end(), idDesign);
|
||
if (it != ids.end()) ids.erase(it);
|
||
|
||
// 取出三个XLine
|
||
AcDbXline xlineStake, xlineGround, xlineDesign;
|
||
AcDbLine line;
|
||
getXLineByDbText(idStake, &xlineStake);
|
||
getXLineByDbText(idGround, &xlineGround);
|
||
getXLineByDbText(idDesign, &xlineDesign);
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> mapStake, mapGround, mapDesign;
|
||
AcGePoint3dArray arrPnts;
|
||
CString str(_T(""));
|
||
for (size_t i = 0; i < ids.size(); ++i)
|
||
{
|
||
arrPnts.removeAll();
|
||
getLineByDbText(ids[i], &line);
|
||
str = getDbTextString(ids[i]);
|
||
|
||
// 进行桩号判断
|
||
line.intersectWith(&xlineStake, AcDb::kOnBothOperands, AcGePlane::kXYPlane, arrPnts);
|
||
if (arrPnts.length() == 1 && StakeTools::IsStakeString(str))
|
||
{
|
||
mapStake.push_back(std::make_pair(arrPnts[0], str));
|
||
continue;
|
||
}
|
||
// 进行地面高程判断
|
||
line.intersectWith(&xlineGround, AcDb::kOnBothOperands, AcGePlane::kXYPlane, arrPnts);
|
||
if (arrPnts.length() == 1 && StakeTools::IsDoubleString(str))
|
||
{
|
||
mapGround.push_back(std::make_pair(arrPnts[0], str));
|
||
continue;
|
||
}
|
||
// 进行设计高程判断
|
||
line.intersectWith(&xlineDesign, AcDb::kOnBothOperands, AcGePlane::kXYPlane, arrPnts);
|
||
if (arrPnts.length() == 1 && StakeTools::IsDoubleString(str))
|
||
{
|
||
mapDesign.push_back(std::make_pair(arrPnts[0], str));
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 排序
|
||
std::sort(mapStake.begin(), mapStake.end(), _com_pnt_psz_pr(xlineStake));
|
||
std::sort(mapGround.begin(), mapGround.end(), _com_pnt_psz_pr(xlineGround));
|
||
std::sort(mapDesign.begin(), mapDesign.end(), _com_pnt_psz_pr(xlineDesign));
|
||
|
||
// 理论上,三个集合的大小应该一至,为了容错,取出最小size
|
||
size_t count = __min(mapStake.size(), mapGround.size());
|
||
count = __min(count, mapDesign.size());
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> ground(0), design(0);
|
||
double dG(.0), dD(.0);
|
||
for (size_t i = 0; i < count; ++i)
|
||
{
|
||
CString &stake = mapStake[i].second;
|
||
dG = _ttof(mapGround[i].second);
|
||
dD = _ttof(mapDesign[i].second);
|
||
ground.push_back(std::make_pair(AcGePoint3d(0, 0, dG), stake));
|
||
design.push_back(std::make_pair(AcGePoint3d(0, 0, dD), stake));
|
||
}
|
||
outputTXTFile(ground, _T("地面高程文件 (*.txt)|*.txt;*.txt||"));
|
||
outputTXTFile(design, _T("设计高程文件 (*.txt)|*.txt;*.txt||"));
|
||
}
|
||
|
||
void generateCenterLineOfRoad()
|
||
{
|
||
CString szFilter = _T("道路中心线数据 (*.txt)|*.txt;*.txt||");
|
||
CFileDialog fileDlg(TRUE, _T("stl"), NULL, OFN_HIDEREADONLY, szFilter, acedGetAcadFrame());
|
||
int nRes = fileDlg.DoModal();
|
||
if (nRes != IDOK) return;
|
||
|
||
CString strFile = fileDlg.GetPathName();
|
||
|
||
if (_taccess(strFile, 0x0) != 0x0) return;
|
||
|
||
CStdioFile file(strFile, CFile::shareDenyRead);
|
||
CString strLine(_T("")), sStake(_T("")), sElev(_T(""));
|
||
std::vector<CString> vecs;
|
||
std::map<double, double, GLTools::compare_double> mapStake;
|
||
double dDist(.0), dElev(.0);
|
||
CString prefix(_T("K"));
|
||
while (file.ReadString(strLine))
|
||
{
|
||
split(strLine, _T(','), vecs);
|
||
if (vecs.size() != 2) continue;
|
||
sStake = vecs[0];
|
||
sElev = vecs[1];
|
||
|
||
if (!StakeTools::IsDoubleString(sElev)) continue;
|
||
|
||
dElev = _convert_<double, string>((LPCTSTR)sElev);
|
||
|
||
// 直接就是桩号距离
|
||
if (StakeTools::IsDoubleString(sStake))
|
||
dDist = _convert_<double, string>((LPCTSTR)sStake);
|
||
else if (StakeTools::analyStakeString(sStake, dDist, &prefix))
|
||
{
|
||
// 空
|
||
}
|
||
else
|
||
continue;
|
||
|
||
mapStake.insert(std::make_pair(dDist, dElev));
|
||
}
|
||
file.Close();
|
||
|
||
// 得到全图的 acdbtext 实体。对比内容,如果内容与文件中的一致,则取文字基点的 x,y 值,且z值为文件中桩号的数据。
|
||
|
||
ads_name ss, ent;
|
||
struct resbuf* pRb = acutBuildList(RTDXF0, _T("TEXT"), 0);
|
||
nRes = acedSSGet(_T("A"), NULL, NULL, pRb, ss);
|
||
if (nRes != RTNORM)
|
||
{
|
||
acutPrintf(_T("\n没有发现桩号文字。"));
|
||
return;
|
||
}
|
||
|
||
bool b;
|
||
std::set<CString> strSet;
|
||
std::pair<std::set<CString>::iterator, bool> pr;
|
||
CString sTxt(_T(""));
|
||
AcGePoint3d ptTxt(AcGePoint3d::kOrigin);
|
||
double d;
|
||
AcDbObjectId id;
|
||
Adesk::Int32 lLen = 0L;
|
||
acedSSLength(ss,&lLen);
|
||
std::vector<std::pair<AcGePoint3d, CString>> pts(0);
|
||
AcString str;
|
||
std::map<double, AcGePoint3d, GLTools::compare_double> mapPt;
|
||
for (long i = 0; i < lLen; i++)
|
||
{
|
||
if (acedSSName(ss,i,ent) != RTNORM) continue;
|
||
if (acdbGetObjectId(id, ent) != Acad::eOk) continue;
|
||
if (!StakeTools::isSHSStake(id)) continue;
|
||
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbText, pTxt)
|
||
if (pTxt != NULL)
|
||
{
|
||
OPENOBJ_BEGIN(pTxt->blockId(), AcDb::kForRead, AcDbBlockTableRecord, pRec)
|
||
if (pRec)
|
||
{
|
||
pRec->getName(str);
|
||
if (CString(ACDB_MODEL_SPACE).CompareNoCase(str) != 0) continue;
|
||
}
|
||
OPENOBJ_END()
|
||
if (!StakeTools::readSHSStake(pTxt, ptTxt, b, sTxt, d, d)) continue;
|
||
if (!StakeTools::analyStakeString(sTxt, dDist)) continue;
|
||
mapPt.insert(std::make_pair(dDist, ptTxt));
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
acedSSFree(ss);
|
||
|
||
std::map<double, double, GLTools::compare_double>::iterator it = mapStake.begin();
|
||
std::map<double, AcGePoint3d, GLTools::compare_double>::iterator itPt;
|
||
for (; it != mapStake.end(); ++it)
|
||
{
|
||
itPt = mapPt.find(it->first);
|
||
if (itPt == mapPt.end()) continue;
|
||
AcGePoint3d pt(itPt->second);
|
||
pt.z = it->second;
|
||
pts.push_back(std::make_pair(pt, StakeTools::generateStakeString(it->first, prefix)));
|
||
}
|
||
|
||
if (pts.empty())
|
||
{
|
||
acutPrintf(_T("\n未找到与文件匹配的桩号。"));
|
||
return;
|
||
}
|
||
|
||
insert3dPoly(pts);
|
||
}
|
||
|
||
void generateCenterLineOfRoadByPoint()
|
||
{
|
||
ads_name ent;
|
||
ads_point adsPt;
|
||
|
||
int nRes;
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> pts(0);
|
||
|
||
AcDbObjectId id;
|
||
while ((nRes = acedEntSel(_T("\n请选择一个文字对象或块对象"), ent, adsPt)) == RTNORM)
|
||
{
|
||
acdbGetObjectId(id, ent);
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt)
|
||
if (pEnt)
|
||
{
|
||
AcDbText *pText = AcDbText::cast(pEnt);
|
||
if (pText)
|
||
pts.push_back(std::make_pair(getDbTextPos(pText), pText->textString()));
|
||
AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt);
|
||
if (pRef)
|
||
pts.push_back(std::make_pair(pRef->position(), _T("")));
|
||
}
|
||
else
|
||
acutPrintf(_T("\n所选择的实体不是文字对象或块对象,请重新选择!"));
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
|
||
insert3dPoly(pts);
|
||
}
|
||
|
||
// 添加总分图线
|
||
void appendDwgCuter_ZT()
|
||
{
|
||
ads_name ent;
|
||
ads_point adsPt;
|
||
int nRes = acedEntSel(_T("\n请选择地面高程线"), ent, adsPt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
// 分图线高度
|
||
double dWidth(80.0);
|
||
// 分图线间隔
|
||
double dSpace(200.0);
|
||
|
||
AcDbObjectId idPoly;
|
||
acdbGetObjectId(idPoly, ent);
|
||
|
||
AcDbPolyline poly;
|
||
if (!poly3D2Poly2D(idPoly, poly))
|
||
{
|
||
acutPrintf(_T("\n请选择由\"地高程线\"命令生成的地面高程线。"));
|
||
return;
|
||
}
|
||
|
||
|
||
if (acedGetReal(_T("\n请输入分图线高度:<80>"), &dWidth) == RTCAN) return;
|
||
if (acedGetReal(_T("\n请输入分图线间隔:<200>"), &dSpace) == RTCAN) return;
|
||
|
||
AcGePoint3d ptFirst(AcGePoint3d::kOrigin);
|
||
ads_point adsPtUCS;
|
||
poly.getStartPoint(ptFirst);
|
||
acdbWcs2Ucs(asDblArray(ptFirst), adsPtUCS, false);
|
||
nRes = acedGetPoint(adsPtUCS, _T("\n请选择地面高程线上一点,做为首个分图线的起点:"), adsPt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
ads_point adsPtWCS;
|
||
acdbUcs2Wcs(adsPt, adsPtWCS, false);
|
||
|
||
AcGePoint3d ptStart(asPnt3d(adsPtWCS)), pt(AcGePoint3d::kOrigin);
|
||
if (poly.getClosestPointTo(ptStart, ptStart) != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n所选择的点无效,请重新选择."));
|
||
return;
|
||
}
|
||
|
||
generateDwgCuter(poly, ptStart, dSpace, dWidth);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
// 添加断分图线
|
||
void appendDwgCuter_ZD()
|
||
{
|
||
ads_name ent;
|
||
ads_point adsPt;
|
||
int nRes = acedEntSel(_T("\n请选择管廊分段:"), ent, adsPt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
AcDbObjectId id;
|
||
acdbGetObjectId(id, ent);
|
||
AcDbObjectIdArray ids;
|
||
OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEarthWorm, pWorm)
|
||
if (!pWorm)
|
||
{
|
||
acutPrintf(_T("\n请选择一段管廊."));
|
||
return;
|
||
}
|
||
GetConnectedWorms(pWorm, ids);
|
||
OPENOBJ_END()
|
||
|
||
// 分图线高度
|
||
double dWidth(80.0);
|
||
// 分图线间隔
|
||
double dSpace(200.0);
|
||
|
||
if (acedGetReal(_T("\n请输入分图线高度:<80>"), &dWidth) == RTCAN) return;
|
||
if (acedGetReal(_T("\n请输入分图线间隔:<200>"), &dSpace) == RTCAN) return;
|
||
|
||
AcDbPolyline *pPoly = new AcDbPolyline;
|
||
for (size_t i = 0; i < ids.length(); ++i)
|
||
{
|
||
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, AecDbEarthWorm, pWorm)
|
||
if (!pWorm) continue;
|
||
pPoly->addVertexAt(i, pWorm->VStartPoint());
|
||
if (i == ids.length() - 1)
|
||
pPoly->addVertexAt(i + 1, pWorm->VEndPoint());
|
||
OPENOBJ_END()
|
||
}
|
||
pPoly->setColorIndex(1);
|
||
AcDbPolyline poly;
|
||
poly.copyFrom(pPoly);
|
||
|
||
AddToModelSpace(pPoly);
|
||
|
||
AcDbObjectId idPoly = pPoly->objectId();
|
||
|
||
|
||
AcGePoint3d ptFirst(AcGePoint3d::kOrigin);
|
||
ads_point adsPtUCS;
|
||
poly.getStartPoint(ptFirst);
|
||
acdbWcs2Ucs(asDblArray(ptFirst), adsPtUCS, false);
|
||
nRes = acedGetPoint(adsPtUCS, _T("\n请选择地面高程线上一点,做为首个分图线的起点:"), adsPt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
ads_point adsPtWCS;
|
||
acdbUcs2Wcs(adsPt, adsPtWCS, false);
|
||
|
||
AcGePoint3d ptStart(asPnt3d(adsPtWCS)), pt(AcGePoint3d::kOrigin);
|
||
if (poly.getClosestPointTo(ptStart, ptStart) != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n所选择的点无效,请重新选择."));
|
||
return;
|
||
}
|
||
|
||
generateDwgCuter(poly, ptStart, dSpace, dWidth);
|
||
|
||
OPENOBJ_BEGIN(idPoly, AcDb::kForWrite, AcDbPolyline, pL)
|
||
if (pL) pL->erase();
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
// 为管廊红线批量插入桩号
|
||
void splite3DPolyline()
|
||
{
|
||
ads_name name;
|
||
ads_point adsPt;
|
||
int nRes = acedEntSel(_T("\n请选择一条3dPolyLine线。"), name, adsPt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
AcDbObjectId idPoly(AcDbObjectId::kNull), idTextStart(AcDbObjectId::kNull), idTextEnd(AcDbObjectId::kNull);
|
||
acdbGetObjectId(idPoly, name);
|
||
|
||
if (!GLTools::isThisClass<AcDb3dPolyline>(idPoly))
|
||
{
|
||
acutPrintf(_T("\n选择的对象不是3DPolyLine。"));
|
||
return;
|
||
}
|
||
|
||
AcDbPolyline poly2d;
|
||
if (!poly3D2Poly2D(idPoly, poly2d))
|
||
{
|
||
acutPrintf(_T("\n曲线转换失败。"));
|
||
return;
|
||
}
|
||
|
||
#if 0
|
||
AcDbPolyline *pL = new AcDbPolyline;
|
||
pL->copyFrom(&poly2d);
|
||
pL->setColorIndex(2);
|
||
AddToModelSpace(pL);
|
||
#endif
|
||
|
||
|
||
|
||
AcGePoint3d pt3DStart(AcGePoint3d::kOrigin), pt3DEnd(AcGePoint3d::kOrigin);
|
||
AcGePoint3d pt2DStart(AcGePoint3d::kOrigin), pt2DEnd(AcGePoint3d::kOrigin);
|
||
|
||
// 起始/线束 桩号字符串
|
||
CString strStart(_T("")), strEnd(_T(""));
|
||
|
||
// 桩号前缀
|
||
CString prefix(_T(""));
|
||
|
||
// 开始桩号上的字符串数值
|
||
double stakeStartValue(.0);
|
||
// 开始/结束 桩号的真实距离
|
||
double startDist(.0), endDist(.0);
|
||
|
||
nRes = acedEntSel(_T("\n请选择一个桩号文字做为开始桩号。"), name, adsPt);
|
||
if (nRes == RTNORM)
|
||
{
|
||
acdbGetObjectId(idTextStart, name);
|
||
if (!GLTools::isThisClass<AcDbText>(idTextStart))
|
||
{
|
||
acutPrintf(_T("\n选择的对象不是文字对象。"));
|
||
return;
|
||
}
|
||
|
||
OPENOBJ_BEGIN(idTextStart, AcDb::kForRead, AcDbText, pTxt)
|
||
strStart = pTxt->textString();
|
||
OPENOBJ_END()
|
||
|
||
// 找到起始点
|
||
if (!findPointByStake(idPoly, strStart, pt3DStart))
|
||
{
|
||
acutPrintf(_T("\n3DPolyline线并没有和%s桩号关联。"), strStart);
|
||
return;
|
||
}
|
||
|
||
if (!StakeTools::analyStakeString(strStart, stakeStartValue, &prefix))
|
||
{
|
||
acutPrintf(_T("\n桩号形式满足要求(例:K1+123)"));
|
||
return;
|
||
}
|
||
|
||
poly2d.getClosestPointTo(pt3DStart, pt2DStart);
|
||
poly2d.getDistAtPoint(pt2DStart, startDist);
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
nRes = acedEntSel(_T("\n请选择一个桩号文字做为结束桩号。<选择终点桩号>"), name, adsPt);
|
||
if (nRes == RTNORM)
|
||
{
|
||
acdbGetObjectId(idTextEnd, name);
|
||
if (!GLTools::isThisClass<AcDbText>(idTextEnd))
|
||
{
|
||
acutPrintf(_T("\n选择的对象不是文字对象。"));
|
||
return;
|
||
}
|
||
|
||
OPENOBJ_BEGIN(idTextEnd, AcDb::kForRead, AcDbText, pTxt)
|
||
strEnd = pTxt->textString();
|
||
OPENOBJ_END()
|
||
|
||
// 找到终点
|
||
if (!findPointByStake(idPoly, strEnd, pt3DEnd))
|
||
{
|
||
acutPrintf(_T("\n3DPolyline线并没有和%s桩号关联。"), strEnd);
|
||
return;
|
||
}
|
||
poly2d.getClosestPointTo(pt3DEnd, pt2DEnd);
|
||
poly2d.getDistAtPoint(pt2DEnd, endDist);
|
||
}
|
||
else
|
||
{
|
||
AcGePoint3d pt(AcGePoint3d::kOrigin);
|
||
poly2d.getEndPoint(pt);
|
||
poly2d.getDistAtPoint(pt, endDist);
|
||
}
|
||
|
||
if (startDist >= endDist)
|
||
{
|
||
acutPrintf(_T("结束桩号应该在起始桩号之后,请重新选择。"));
|
||
return;
|
||
}
|
||
|
||
double dSpace(20.0);
|
||
nRes = acedGetReal(_T("\n请输入桩号间距<20>"), &dSpace);
|
||
if (nRes == RTERROR) return;
|
||
|
||
AcGePoint3d pt2D, pt3D;
|
||
CString sStake(_T(""));
|
||
while (startDist < endDist)
|
||
{
|
||
startDist += dSpace;
|
||
stakeStartValue += dSpace;
|
||
|
||
poly2d.getPointAtDist(startDist, pt2D);
|
||
pt3D = get3DPtFrom3DPolyline(idPoly, pt2D);
|
||
if (Is3DPolylineNode(idPoly, pt3D)) continue;
|
||
|
||
sStake = StakeTools::generateStakeString(stakeStartValue, prefix);
|
||
AcDbText *p = makeSameText(idTextStart, sStake, pt3D);
|
||
AddToModelSpace(p);
|
||
//insertTo3DPolyline(idPoly, pt3D);
|
||
#if 0
|
||
AcDbCircle *pC = new AcDbCircle;
|
||
pC->setCenter(pt2D);
|
||
pC->setRadius(1);
|
||
AddToModelSpace(pC);
|
||
pC = new AcDbCircle;
|
||
pC->setCenter(pt3D);
|
||
pC->setRadius(1);
|
||
AddToModelSpace(pC);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
// 为道路中心线批量插入桩号
|
||
void spliteCenterLine()
|
||
{
|
||
assert(false);
|
||
ads_point pt;
|
||
ads_name ent;
|
||
int nRes;
|
||
|
||
// 选择中心线
|
||
AcDbObjectId idCenter = getCenterRoldLine(_T("\n请选择道路中心线。"), _T("LWPOLYLINE,LINE,ARC"));
|
||
if (!idCenter.isValid())
|
||
{
|
||
acutPrintf(_T("\n未找到道路中心线,请选择一个(多段线,直线或弧线对象)。"));
|
||
return;
|
||
}
|
||
|
||
if (!GLTools::isThisClass<AcDbCurve>(idCenter)) return;
|
||
|
||
// 起始桩号,结束桩号
|
||
bool bThousands(false); // 桩号形式
|
||
CString sPrefix(_T("")); // 桩号前缀
|
||
CString sStakeStart(_T("")), sStakeEnd(_T("")); // 桩号文字
|
||
double dTextDistStart(.0), dTextDistEnd(.0); // 桩号文字所表示的距离
|
||
double dDistOnLineStart(.0), dDistOnLineEnd(.0); // 文字投射到曲线上的点的距离
|
||
AcGePoint3d ptStakeStart(AcGePoint3d::kOrigin), ptStakeEnd(AcGePoint3d::kOrigin); // 桩号文字与曲线交点
|
||
AcDbObjectId idTextStart(AcDbObjectId::kNull), idTextEnd(AcDbObjectId::kNull);
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
nRes = acedEntSel(_T("\n请选择起始参考桩号:"), ent, pt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
acdbGetObjectId(idTextStart, ent);
|
||
if (!GLTools::isThisClass<AcDbText>(idTextStart))
|
||
{
|
||
acutPrintf(_T("\n请选择一个文字对象。"));
|
||
return;
|
||
}
|
||
|
||
sStakeStart = getDbTextString(idTextStart);
|
||
if (!StakeTools::analyStakeString(sStakeStart, dTextDistStart, &sPrefix, &bThousands))
|
||
{
|
||
acutPrintf(_T("\n选择的文字对象不是桩号。"));
|
||
return;
|
||
}
|
||
|
||
if (!getIntersectPoint(idTextStart, idCenter, ptStakeStart))
|
||
{
|
||
acutPrintf(_T("\n文字方向延长线不与选中的polyline相交。"));
|
||
return;
|
||
}
|
||
//////////////////////////////////////////////////////////////////////////
|
||
nRes = acedEntSel(_T("\n请选择结束参考桩号:"), ent, pt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
acdbGetObjectId(idTextEnd, ent);
|
||
if (!GLTools::isThisClass<AcDbText>(idTextEnd))
|
||
{
|
||
acutPrintf(_T("\n请选择一个文字对象。"));
|
||
return;
|
||
}
|
||
|
||
sStakeEnd = getDbTextString(idTextEnd);
|
||
if (!StakeTools::analyStakeString(sStakeEnd, dTextDistEnd, &sPrefix))
|
||
{
|
||
acutPrintf(_T("\n选择的文字对象不是桩号。"));
|
||
return;
|
||
}
|
||
|
||
if (!getIntersectPoint(idTextEnd, idCenter, ptStakeEnd))
|
||
{
|
||
acutPrintf(_T("\n文字方向延长线不与选中的polyline相交。"));
|
||
return;
|
||
}
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
double dSpace(20);
|
||
acedGetReal(_T("\n请输入桩号之间距离<20>"), &dSpace);
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
getDistAtPoint(idCenter, ptStakeStart, dDistOnLineStart);
|
||
getDistAtPoint(idCenter, ptStakeEnd, dDistOnLineEnd);
|
||
|
||
CString newStake(_T("")); // 新桩号字符串
|
||
double newOnLineDist(.0); // 新桩号与曲线的交点在曲线上的距离
|
||
double newStakeDist(.0); // 新桩号与曲线的交点在曲线上的距离
|
||
AcGePoint3d ptIns(AcGePoint3d::kOrigin);// 新桩号插入点
|
||
AcGeVector3d vtOld(AcGeVector3d::kXAxis), vtCut(AcGeVector3d::kIdentity);
|
||
// 曲线方向与桩号方向一至
|
||
bool bSameDir((dDistOnLineEnd - dDistOnLineStart) * (dTextDistEnd - dTextDistStart) > 0);
|
||
|
||
newOnLineDist = dDistOnLineStart + (bSameDir ? 1 : -1) * dSpace;
|
||
newStakeDist = dTextDistStart + dSpace;
|
||
|
||
std::map<double, AcDbObjectId, GLTools::compare_double> mapStakes;
|
||
getAllStake(mapStakes);
|
||
|
||
while (newStakeDist < dTextDistEnd)
|
||
{
|
||
if (!bThousands)
|
||
newStake.Format(_T("%s+%.3f"), sPrefix, newStakeDist);
|
||
else
|
||
newStake = StakeTools::generateStakeString(newStakeDist, sPrefix);
|
||
|
||
if (getPointAtDist(idCenter, newOnLineDist, ptIns) != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n根据距离取点出错。%s"), newStake);
|
||
continue;
|
||
}
|
||
|
||
newOnLineDist = newOnLineDist + (bSameDir ? 1 : -1) * dSpace;
|
||
newStakeDist = newStakeDist + dSpace;
|
||
|
||
vtOld = AcGeVector3d::kXAxis;
|
||
vtCut = AcGeVector3d::kIdentity;
|
||
if (getFirstDeriv(idCenter, ptIns, vtCut) != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n取导数出错。%s"), newStake);
|
||
continue;
|
||
}
|
||
|
||
if (mapStakes.find(newStakeDist - dSpace) != mapStakes.end())
|
||
{
|
||
acutPrintf(_T("\n找到重复桩号%s。"), newStake);
|
||
continue;
|
||
}
|
||
|
||
AcDbText *pText(NULL);
|
||
OPENOBJ_BEGIN(idTextStart, AcDb::kForRead, AcDbText, pTxt)
|
||
pText = (AcDbText*)pTxt->clone();
|
||
vtOld.rotateBy(pTxt->rotation(), AcGeVector3d::kZAxis);
|
||
OPENOBJ_END()
|
||
|
||
// 得到文字方向
|
||
vtCut.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
if (vtCut.dotProduct(vtOld) < 0)
|
||
vtCut.rotateBy(PI, AcGeVector3d::kZAxis);
|
||
|
||
double angle = vtCut.angleTo(AcGeVector3d::kXAxis);
|
||
pText->setRotation(angle);
|
||
|
||
pText->setTextString(newStake);
|
||
pText->horizontalMode();
|
||
if (pText->horizontalMode() == AcDb::kTextLeft && pText->verticalMode() == AcDb::kTextBottom)
|
||
pText->setPosition(ptIns);
|
||
else
|
||
pText->setAlignmentPoint(ptIns);
|
||
|
||
AddToModelSpace(pText);
|
||
}
|
||
}
|
||
|
||
// 添加桩号
|
||
void addStake()
|
||
{
|
||
AcDbObjectId idStartTxt(AcDbObjectId::kNull), idEndTxt(AcDbObjectId::kNull), idPoly(AcDbObjectId::kNull);
|
||
ads_point pt;
|
||
|
||
int nRes;
|
||
|
||
idPoly = getCenterRoldLine(_T("\n请选择道路中心线(Polyline对象)。"), _T("LWPOLYLINE,LINE,ARC"));
|
||
|
||
if (!GLTools::isThisClass<AcDbCurve>(idPoly))
|
||
{
|
||
acutPrintf(_T("\n请选择一个Polyline对象。"));
|
||
return;
|
||
}
|
||
|
||
double dOrigStakeDistStart(.0);
|
||
CString strPrefix(_T("")), strNew(_T(""));
|
||
bool bThousands(false);
|
||
bool bStart2End(true);
|
||
AcGePoint3d ptStartStake(AcGePoint3d::kOrigin);
|
||
|
||
|
||
if (!getSHSStake(_T("\n请选择起始参考桩号:"), idStartTxt, dOrigStakeDistStart, strPrefix, bStart2End, bThousands, &ptStartStake)) return;
|
||
|
||
double dist(.0) // 用户输入距离
|
||
, dSel(.0) // 用户点选点的距离
|
||
, dOrigIntersctDistStart(.0) // 起始桩号文字对象在中心线上的距离
|
||
, dNewDist // 新桩号距离
|
||
, dOrigIntersctDistEnd(.0); // 结束桩号文字对象在中心线上的距离
|
||
AcGePoint3d ptSel(AcGePoint3d::kOrigin);
|
||
|
||
AcGeVector3d vtCut(AcGeVector3d::kIdentity);
|
||
AcGePoint3d ptIns(AcGePoint3d::kOrigin), ptEndStake(AcGePoint3d::kOrigin);
|
||
AcGePoint3dArray pts;
|
||
|
||
getDistAtPoint(idPoly, ptStartStake, dOrigIntersctDistStart);
|
||
|
||
TCHAR szKey[131] = {};
|
||
acedInitGet(RSG_OTHER, _T("D P"));
|
||
nRes = acedGetKword(_T("\n请选择[输入新桩号距离(D)/点选新桩号位置(P)]<点选新桩号位置(P)>:"), szKey);
|
||
|
||
if (nRes == RTNONE)
|
||
_tcscpy(szKey, _T("P"));
|
||
else if (nRes == RTCAN)
|
||
return;
|
||
|
||
if (_tcscmp(szKey,_T("D")) == 0)
|
||
{
|
||
nRes = acedGetReal(_T("\n请输入距此桩号的距离:"), &dist);
|
||
if (nRes != RTNORM) return;
|
||
dOrigIntersctDistStart += (bStart2End ? 1 : -1) * dist;
|
||
getPointAtDist(idPoly, dOrigIntersctDistStart, ptIns);
|
||
dNewDist = dOrigStakeDistStart + dist;
|
||
}
|
||
else
|
||
{
|
||
acdbWcs2Ucs(asDblArray(ptStartStake), pt, false);
|
||
nRes = acedGetPoint(pt, _T("\n选择新桩号位置。"), pt);
|
||
if (nRes != RTNORM) return;
|
||
acdbUcs2Wcs(pt, pt, false);
|
||
ptSel = asPnt3d(pt);
|
||
if (getClosestPointTo(idPoly, ptSel, ptSel) != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n选择点不在polyline范围内。"));
|
||
return;
|
||
}
|
||
ptIns = ptSel;
|
||
getDistAtPoint(idPoly, ptSel, dSel);
|
||
dNewDist = dOrigStakeDistStart +(bStart2End ? 1 : -1) * (dSel - dOrigIntersctDistStart);
|
||
}
|
||
|
||
getFirstDeriv(idPoly, ptIns, vtCut);
|
||
|
||
if (!bThousands)
|
||
strNew.Format(_T("%s+%.2f"), strPrefix, dNewDist);
|
||
else
|
||
strNew = StakeTools::generateStakeString(dNewDist, strPrefix);
|
||
|
||
AcDbText *pText(NULL);
|
||
AcGeVector3d vtOld(AcGeVector3d::kXAxis), vtNew(AcGeVector3d::kXAxis);
|
||
OPENOBJ_BEGIN(idStartTxt, AcDb::kForRead, AcDbText, pTxt)
|
||
pText = (AcDbText*)pTxt->clone();
|
||
vtOld.rotateBy(pTxt->rotation(), AcGeVector3d::kZAxis);
|
||
OPENOBJ_END()
|
||
|
||
// 读批量插桩对话框缓存
|
||
CGenerateStakeDlg dlg;
|
||
CString s = dlg.m_strPrefix;
|
||
double dL = dlg.m_dStakeL * .5;
|
||
double dW = dlg.m_dStakeW;
|
||
double txtH = dlg.m_dTxtH;
|
||
int nPosition = dlg.m_nPositonOfStake; // 桩号位置(左右中,012)
|
||
int nReadDir = dlg.m_nReaderDir; // 文字阅读方向
|
||
CString style = dlg.m_strStyle;
|
||
double txtWF = dlg.m_dTxtWF;
|
||
|
||
// 得到文字方向
|
||
if (vtCut.dotProduct(vtOld) < 0)
|
||
vtCut.rotateBy(PI, AcGeVector3d::kZAxis);
|
||
vtCut.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
if (vtCut.dotProduct(vtOld) < 0)
|
||
vtCut.rotateBy(PI, AcGeVector3d::kZAxis);
|
||
pText->setTextString(strNew);
|
||
pText->setHeight(txtH);
|
||
AcDbObjectId styleId = GLTools::getTextStyle(style);
|
||
if (styleId.isValid())
|
||
pText->setTextStyle(styleId);
|
||
pText->setWidthFactor(txtWF);
|
||
|
||
|
||
// 插入桩线
|
||
|
||
vtCut.normalize();
|
||
AcGePoint3d ptFirst(ptIns), ptSecond(ptIns);
|
||
ptFirst += vtCut * dL;
|
||
ptSecond -= vtCut * dL;
|
||
AcDbPolyline *pL = new AcDbPolyline;
|
||
pL->addVertexAt(0, ptFirst.convert2d(AcGePlane::kXYPlane), 0, dW, dW);
|
||
pL->addVertexAt(1, ptSecond.convert2d(AcGePlane::kXYPlane), 0, dW, dW);
|
||
|
||
AcGeVector3d vtD(AcGeVector3d::kIdentity);
|
||
getFirstDeriv(idPoly, ptIns, vtD);
|
||
vtD.normalize();
|
||
AcGeVector3d vtVertical(vtD);
|
||
vtVertical.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
vtVertical.normalize();
|
||
double angle = AcGeVector3d::kXAxis.angleTo(vtVertical, AcGeVector3d::kZAxis) + PI;
|
||
if (nReadDir == 1) // 下至上
|
||
angle -= PI;
|
||
pText->setRotation(angle);
|
||
ptFirst = ptSecond = ptIns;
|
||
ptFirst += vtVertical * dL;
|
||
ptSecond -= vtVertical * dL;
|
||
|
||
AcGePoint3d ptTxt;
|
||
switch (nPosition)
|
||
{
|
||
case 0: // 左
|
||
pText->setHorizontalMode((nReadDir == 0) ? AcDb::kTextRight : AcDb::kTextLeft);
|
||
ptTxt = ptFirst + vtVertical * (dL + .2);
|
||
break;
|
||
case 1: // 右
|
||
pText->setHorizontalMode((nReadDir == 0) ? AcDb::kTextLeft : AcDb::kTextRight);
|
||
ptTxt = ptSecond - vtVertical * (dL + .2);
|
||
break;
|
||
case 2: // 中
|
||
pText->setHorizontalMode(AcDb::kTextCenter);
|
||
ptTxt = ptIns;
|
||
// 再沿切线方向移半个字高
|
||
ptTxt += vtD * txtH;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
pText->setAlignmentPoint(ptTxt);
|
||
|
||
double pointDist(.0);
|
||
getDistAtPoint(idPoly, ptIns, pointDist);
|
||
StakeTools::writeSHSStakeFlag(pText, ptIns, bStart2End, strNew, dNewDist, pointDist);
|
||
StakeTools::writeSHSStakeFlag(pL, ptIns, bStart2End, strNew, dNewDist, pointDist);
|
||
|
||
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_Stake);
|
||
g_LayerMgr::instance().setLayer(pL, GLTools::gLayer_Stake);
|
||
|
||
AddToModelSpace(pText);
|
||
AddToModelSpace(pL);
|
||
}
|
||
|
||
// 批量生成桩号
|
||
void generateStake()
|
||
{
|
||
Acad::ErrorStatus es;
|
||
|
||
// 选择中心线
|
||
AcDbObjectId idCenter = getCenterRoldLine(_T("\n请选择道路中心线。"), _T("LWPOLYLINE,LINE,ARC,AEC_ROADAXISLINE"));
|
||
if (!idCenter.isValid())
|
||
{
|
||
acutPrintf(_T("\n未找到道路中心线,请选择一个(多段线,直线或弧线或道路线实体)。"));
|
||
return;
|
||
}
|
||
|
||
ads_point adsPt;
|
||
|
||
// 选择中心线上一点做为桩号起点
|
||
int nRes = acedGetPoint(NULL, _T("选择中心线上一点做为桩号起点"), adsPt);
|
||
if (nRes != RTNORM) return;
|
||
acdbUcs2Wcs(adsPt, adsPt, false);
|
||
|
||
AcGePoint3d ptFirst(AcGePoint3d::kOrigin), ptSecond(AcGePoint3d::kOrigin), ptIns(AcGePoint3d::kOrigin);
|
||
|
||
double dSelDistFirst(.0), dSelDistSecond(.0), dCenterLen(.0);
|
||
|
||
OPENOBJ_BEGIN(idCenter, AcDb::kForWrite, AcDbCurve, pCenter)
|
||
{
|
||
if (!pCenter)
|
||
{
|
||
acutPrintf(_T("\n所选中心线有误。"));
|
||
return;
|
||
}
|
||
es = pCenter->getClosestPointTo(asPnt3d(adsPt), AcGeVector3d::kZAxis, ptFirst);
|
||
if (es != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n所选点并不在中心线附近。"));
|
||
return;
|
||
}
|
||
|
||
AcGePoint3d ptEnd(AcGePoint3d::kOrigin);
|
||
pCenter->getEndPoint(ptEnd);
|
||
pCenter->getDistAtPoint(ptEnd, dCenterLen);
|
||
|
||
pCenter->getDistAtPoint(ptFirst, dSelDistFirst);
|
||
|
||
// 选择第二点,用来确定布置方向
|
||
acdbWcs2Ucs(asDblArray(ptFirst), adsPt, false);
|
||
int nRes = acedGetPoint(adsPt, _T("选择中心线上另外一点,用以确定布置方向。"), adsPt);
|
||
if (nRes != RTNORM) return;
|
||
acdbUcs2Wcs(adsPt, adsPt, false);
|
||
es = pCenter->getClosestPointTo(asPnt3d(adsPt), AcGeVector3d::kZAxis, ptSecond);
|
||
if (es != Acad::eOk)
|
||
{
|
||
acutPrintf(_T("\n所选点并不在中心线附近。"));
|
||
return;
|
||
}
|
||
pCenter->getDistAtPoint(ptSecond, dSelDistSecond);
|
||
|
||
if (dSelDistFirst > dSelDistSecond)
|
||
{
|
||
acutPrintf(_T("\n布置桩号方向与中心线方向相反,将反转中心线!"));
|
||
AcDbPolyline* pPl = AcDbPolyline::cast(pCenter);
|
||
if (pPl != NULL)
|
||
{
|
||
reverseCurve(pPl);
|
||
}
|
||
}
|
||
pCenter->getDistAtPoint(ptFirst, dSelDistFirst);
|
||
}
|
||
OPENOBJ_END()
|
||
|
||
//bool bStartDir = dSelDistSecond > dSelDistFirst; // ture 从中心线的起点开始布置,false 从中心线的终点开始布置
|
||
bool bStartDir = true; // ture 从中心线的起点开始布置,false 从中心线的终点开始布置
|
||
|
||
// 弹出对话框
|
||
CAcModuleResourceOverride myResources;
|
||
CGenerateStakeDlg dlg;
|
||
|
||
if (bStartDir)
|
||
dlg.m_dDistStart = dSelDistFirst;
|
||
else
|
||
dlg.m_dDistStart = dCenterLen - dSelDistFirst;
|
||
|
||
dlg.m_dDistEnd = dCenterLen;
|
||
|
||
if (dlg.DoModal() != IDOK) return;
|
||
CString strPrefix = dlg.m_strPrefix; // 桩号前缀
|
||
strPrefix += _T("K");
|
||
double distStart = dlg.m_dDistStart; // 起始桩号距离
|
||
double distEnd = dlg.m_dDistEnd; // 结束桩号距离
|
||
double dSpace = dlg.m_dSpace; // 桩号间距
|
||
double txtH = dlg.m_dTxtH; // 桩号字高
|
||
double txtWF = dlg.m_dTxtWF; // 文字宽度因子
|
||
AcDbObjectId idStyle = dlg.m_idStyle; // 文字样式
|
||
double dStakeL = dlg.m_dStakeL * .5; // 桩线长
|
||
double dStakeW = dlg.m_dStakeW; // 桩线宽
|
||
int nPosition = dlg.m_nPositonOfStake; // 桩号位置(左右中,012)
|
||
int nReadDir = dlg.m_nReaderDir; // 文字阅读方向
|
||
|
||
// 取整
|
||
// distStart = roundUpNum(distStart, 10);
|
||
// distEnd = roundUpNum(distEnd, 10);
|
||
|
||
CString strStake(_T(""));
|
||
|
||
OPENOBJ_BEGIN(idCenter, AcDb::kForRead, AcDbCurve, pCenter)
|
||
{
|
||
if (!pCenter) return;
|
||
|
||
double dist(.0), angle(.0);
|
||
AcGeVector3d vtVertical(AcGeVector3d::kIdentity), vtTangent(AcGeVector3d::kIdentity);
|
||
pCenter->getDistAtPoint(ptFirst, dist);
|
||
|
||
bool bBreak(false);
|
||
while (distStart <= distEnd)
|
||
{
|
||
if (bBreak) break;
|
||
es = pCenter->getPointAtDist(dist, ptIns);
|
||
if (es != Acad::eOk)
|
||
{
|
||
double d;
|
||
pCenter->getEndPoint(ptIns);
|
||
pCenter->getDistAtPoint(ptIns, d);
|
||
distStart -= dSpace;
|
||
dist -= dSpace;
|
||
distStart += d - dist;
|
||
dist += d - dist;
|
||
bBreak = true;
|
||
}
|
||
|
||
ptSecond = ptFirst = ptIns;
|
||
|
||
AcDbText *pText = new AcDbText();
|
||
strStake = StakeTools::generateStakeString(distStart, strPrefix);
|
||
pText->setTextString(strStake);
|
||
pText->setHeight(txtH);
|
||
pText->setTextStyle(idStyle);
|
||
pText->setVerticalMode(AcDb::kTextVertMid);
|
||
pText->setWidthFactor(txtWF);
|
||
|
||
pCenter->getFirstDeriv(ptFirst, vtTangent);
|
||
vtVertical = vtTangent;
|
||
vtVertical.rotateBy(PI * .5, AcGeVector3d::kZAxis);
|
||
angle = AcGeVector3d::kXAxis.angleTo(vtVertical, AcGeVector3d::kZAxis) + PI;
|
||
if (nReadDir == 1) // 下至上
|
||
angle -= PI;
|
||
pText->setRotation(angle);
|
||
|
||
// 生成小桩
|
||
vtVertical.normalize();
|
||
vtTangent.normalize();
|
||
ptFirst += vtVertical * dStakeL;
|
||
ptSecond -= vtVertical * dStakeL;
|
||
AcDbPolyline *pLine = new AcDbPolyline;
|
||
pLine->addVertexAt(0, ptFirst.convert2d(AcGePlane::kXYPlane), 0., dStakeW, dStakeW);
|
||
pLine->addVertexAt(1, ptSecond.convert2d(AcGePlane::kXYPlane), 0., dStakeW, dStakeW);
|
||
|
||
|
||
AcGePoint3d ptTxt;
|
||
switch (nPosition)
|
||
{
|
||
case 0: // 左
|
||
pText->setHorizontalMode((nReadDir == 0) ? AcDb::kTextRight : AcDb::kTextLeft);
|
||
ptTxt = ptFirst + vtVertical * (dStakeL + .2);
|
||
break;
|
||
case 1: // 右
|
||
pText->setHorizontalMode((nReadDir == 0) ? AcDb::kTextLeft : AcDb::kTextRight);
|
||
ptTxt = ptSecond - vtVertical * (dStakeL + .2);
|
||
break;
|
||
case 2: // 中
|
||
pText->setHorizontalMode(AcDb::kTextCenter);
|
||
ptTxt = ptIns;
|
||
// 再沿切线方向移半个字高
|
||
ptTxt += vtTangent * txtH;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
pText->setAlignmentPoint(ptTxt);
|
||
|
||
// 写扩展数据
|
||
StakeTools::writeSHSStakeFlag(pText, ptIns, bStartDir, strStake, distStart, dist);
|
||
StakeTools::writeSHSStakeFlag(pLine, ptIns, bStartDir, strStake, distStart, dist);
|
||
|
||
g_LayerMgr::instance().setLayer(pText, GLTools::gLayer_Stake);
|
||
g_LayerMgr::instance().setLayer(pLine, GLTools::gLayer_Stake);
|
||
|
||
AddToModelSpace(pText);
|
||
AddToModelSpace(pLine);
|
||
|
||
dist += (bStartDir ? 1 : -1) * dSpace;
|
||
if (EQUAL_ZERO(dist)) dist = .0;
|
||
|
||
distStart += dSpace;
|
||
}
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
// 桩号高程映射
|
||
void mapStack2Polyline()
|
||
{
|
||
// 读取一个高程文件
|
||
CString szFilter = _T("高程数据文件 (*.*)|*.*;*.*||");
|
||
CFileDialog fileDlg(TRUE, _T("stl"), NULL, OFN_HIDEREADONLY, szFilter, acedGetAcadFrame());
|
||
int nRes = fileDlg.DoModal();
|
||
if (nRes != IDOK) return;
|
||
|
||
CString strFile = fileDlg.GetPathName();
|
||
std::map<double, double, GLTools::compare_double> mapStake;
|
||
analyElevationFile(strFile, mapStake);
|
||
if (mapStake.empty())
|
||
{
|
||
acutPrintf(_T("\n文件内容为空,请检查。"));
|
||
return;
|
||
}
|
||
|
||
ads_name adsName;
|
||
ads_point adsPt;
|
||
|
||
nRes = acedEntSel(_T("\n请选择要映射的polyline线。"), adsName, adsPt);
|
||
if (nRes != RTNORM) return;
|
||
|
||
AcDbObjectId idPoly(AcDbObjectId::kNull);
|
||
acdbGetObjectId(idPoly, adsName);
|
||
|
||
if (!GLTools::isThisClass<AcDbPolyline>(idPoly))
|
||
{
|
||
acutPrintf(_T("\n所选择的实体不是polyline。"));
|
||
return;
|
||
}
|
||
|
||
// 遍历模型空间中所有的文字对象,
|
||
|
||
ads_name ss, ent;
|
||
struct resbuf* pRb = acutBuildList(RTDXF0, _T("TEXT"), 0);
|
||
nRes = acedSSGet(_T("A"), NULL, NULL, pRb, ss);
|
||
if (nRes != RTNORM)
|
||
{
|
||
acutPrintf(_T("\n没有发现文字对象。"));
|
||
return;
|
||
}
|
||
CString sTxt(_T(""));
|
||
AcGePoint3d ptTxt(AcGePoint3d::kOrigin);
|
||
AcDbObjectId id;
|
||
Adesk::Int32 lLen = 0L;
|
||
acedSSLength(ss, &lLen);
|
||
AcString str;
|
||
std::map<double, std::pair<AcGePoint3d, AcDbLine>, GLTools::compare_double> mapPt;
|
||
std::vector<STakeInfo> stakes(0);
|
||
STakeInfo info;
|
||
std::set<CString> setStr;
|
||
std::pair<std::set<CString>::iterator, bool> pr;
|
||
for (long i = 0; i < lLen; i++)
|
||
{
|
||
if (acedSSName(ss, i, ent) != RTNORM) continue;
|
||
if (acdbGetObjectId(id, ent) != Acad::eOk) continue;
|
||
if (!GLTools::isThisClass<AcDbText>(id)) continue;
|
||
if (!StakeTools::isSHSStake(id)) continue;
|
||
if (!info.init(id, mapStake)) continue;
|
||
pr = setStr.insert(info.stake);
|
||
if (pr.second)
|
||
stakes.push_back(info);
|
||
}
|
||
acedSSFree(ss);
|
||
|
||
std::sort(stakes.begin(), stakes.end(), STakeInfo::compare_dist());
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> insPts(0);
|
||
AcGePoint3dArray pts;
|
||
AcGePoint3d pt(AcGePoint3d::kOrigin);
|
||
AcDbXline line;
|
||
OPENOBJ_BEGIN(idPoly, AcDb::kForRead, AcDbPolyline, pPoly)
|
||
for (size_t i = 0; i < stakes.size(); ++i)
|
||
{
|
||
STakeInfo &st = stakes[i];
|
||
pts.removeAll();
|
||
getXLineByDbText(st.id, &line);
|
||
pPoly->intersectWith(&line, AcDb::kOnBothOperands, AcGePlane::kXYPlane, pts);
|
||
if (pts.isEmpty())
|
||
{
|
||
acutPrintf(_T("/n桩号:%s 并没有与选中的polyline相交。"), st.stake);
|
||
continue;
|
||
}
|
||
pt = pts[0];
|
||
pt.z = st.elev;
|
||
insPts.push_back(std::make_pair(pt, st.stake));
|
||
}
|
||
OPENOBJ_END()
|
||
|
||
insert3dPoly(insPts);
|
||
}
|
||
|
||
// 通过点选绘制管廊红线
|
||
void drawRedLineByCustom()
|
||
{
|
||
// 先选择由 “纵断复线” 生成的高程文件
|
||
acutPrintf(_T("\n请选择由 “纵断复线” 生成的高程文件。"));
|
||
CString szFilter = _T("高程数据文件 (*.txt)|*.txt|所有文件(*.*)|*.*||");
|
||
CFileDialog fileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter, acedGetAcadFrame());
|
||
int nRes = fileDlg.DoModal();
|
||
if (nRes != IDOK) return;
|
||
|
||
// 收集所有上华桩号
|
||
std::vector<AcDbObjectId> ids(0);
|
||
StakeTools::getSHSStakeOfAll(ids, false);
|
||
if (ids.empty())
|
||
{
|
||
acutPrintf(_T("\n未找到上华桩号。"));
|
||
return;
|
||
}
|
||
|
||
CString prefix = getDbTextString(ids[0]);
|
||
double _d;
|
||
StakeTools::analyStakeString(prefix, _d, &prefix);
|
||
|
||
CString strFile = fileDlg.GetPathName();
|
||
D2DMap mapStake;
|
||
analyElevationFile(strFile, mapStake);
|
||
if (mapStake.empty())
|
||
{
|
||
acutPrintf(_T("\n文件内容为空,请检查。"));
|
||
return;
|
||
}
|
||
|
||
AcDbObjectId centerID, polyID;
|
||
ads_name adsEnt;
|
||
ads_point adsPt;
|
||
|
||
nRes = acedEntSel(_T("\n请选择道路中心线。"), adsEnt, adsPt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(centerID, adsEnt);
|
||
if (!GLTools::isThisClass<AcDbCurve>(centerID))
|
||
{
|
||
acutPrintf(_T("\n所选对象不是曲线对象。"));
|
||
return;
|
||
}
|
||
|
||
nRes = acedEntSel(_T("\n请选择一条polyline做为管廊的走向。"), adsEnt, adsPt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(polyID, adsEnt);
|
||
if (!GLTools::isThisClass<AcDbPolyline>(polyID))
|
||
{
|
||
acutPrintf(_T("\n所选对象不是polyline对象。"));
|
||
return;
|
||
}
|
||
|
||
// 判断两根线方向,如果polyline不与centerline方向一至,则将polyline反转
|
||
makeSameDir(polyID, centerID);
|
||
|
||
AcGePoint3d ptOrign(AcGePoint3d::kOrigin), ptOver(AcGePoint3d::kOrigin)
|
||
, ptStart(AcGePoint3d::kOrigin), ptEnd(AcGePoint3d::kOrigin);
|
||
|
||
double stakeDistStart(.0), stakeDistEnd(.0);
|
||
double elevStart(.0), elevEnd(.0);
|
||
|
||
nRes = acedGetPoint(adsPt, _T("\n选择管廊走向polyline上的一个点,做为管廊起点。"), adsPt);
|
||
if (nRes != RTNORM) return;
|
||
acdbUcs2Wcs(adsPt, adsPt, false);
|
||
ptStart = asPnt3d(adsPt);
|
||
ptStart.z = .0;
|
||
ptOrign = ptStart;
|
||
getClosestPointTo(polyID, ptOrign, ptOrign);
|
||
getClosestPointTo(centerID, ptStart, ptStart);
|
||
if (!StakeTools::getDistByPointForCenterLine(ids, centerID, ptStart, stakeDistStart))
|
||
{
|
||
acutPrintf(_T("\n提取起点桩号失败。"));
|
||
return;
|
||
}
|
||
if (!getElevationByStakeDist(stakeDistStart, mapStake, elevStart))
|
||
{
|
||
acutPrintf(_T("\n提取起点高程失败。"));
|
||
return;
|
||
}
|
||
|
||
acdbWcs2Ucs(adsPt, adsPt, false);
|
||
nRes = acedGetPoint(adsPt, _T("\n选择管廊走向polyline上的一个点,做为管廊终点。"), adsPt);
|
||
if (nRes != RTNORM) return;
|
||
acdbUcs2Wcs(adsPt, adsPt, false);
|
||
ptEnd = asPnt3d(adsPt);
|
||
ptEnd.z = .0;
|
||
ptOver = ptEnd;
|
||
getClosestPointTo(polyID, ptOver, ptOver);
|
||
getClosestPointTo(centerID, ptEnd, ptEnd);
|
||
if (!StakeTools::getDistByPointForCenterLine(ids, centerID, ptEnd, stakeDistEnd))
|
||
{
|
||
acutPrintf(_T("\n提取终点桩号失败。"));
|
||
return;
|
||
}
|
||
if (!getElevationByStakeDist(stakeDistEnd, mapStake, elevEnd))
|
||
{
|
||
acutPrintf(_T("\n提取终点高程失败。"));
|
||
return;
|
||
}
|
||
|
||
acutPrintf(_T("\n起点桩号 距离:(%.3f) 高程:(%.3f)"), stakeDistStart, elevStart);
|
||
acutPrintf(_T("\n终点桩号 距离:(%.3f) 高程:(%.3f)"), stakeDistEnd, elevEnd);
|
||
acutPrintf(_T("\n******************************"));
|
||
|
||
double dSpace(20.);
|
||
nRes = acedGetReal(_T("\n输入间距<20>:"), &dSpace);
|
||
|
||
///
|
||
AcDbPolyline *pClonePoly(NULL);
|
||
OPENOBJ_BEGIN(polyID, AcDb::kForRead, AcDbPolyline, pL)
|
||
{
|
||
if (!pL) return;
|
||
pClonePoly = (AcDbPolyline*)pL->clone();
|
||
}
|
||
OPENOBJ_END()
|
||
if (!pClonePoly) return;
|
||
|
||
// 将选中的两点插到polyline上
|
||
insertVertexForPolyline(pClonePoly, ptOrign);
|
||
insertVertexForPolyline(pClonePoly, ptOver);
|
||
|
||
// cut
|
||
AcDbPolyline* pp = cutPolyline(pClonePoly, ptOrign, ptOver);
|
||
if (!pp) return;
|
||
DELETE_PTR(pClonePoly);
|
||
pClonePoly = pp;
|
||
pp = NULL;
|
||
|
||
// 合并polyline
|
||
pp = MergePolyline(pClonePoly);
|
||
if (!pp) return;
|
||
DELETE_PTR(pClonePoly);
|
||
pClonePoly = pp;
|
||
pp = NULL;
|
||
|
||
double dCurveLen(.0), stakeDist(.0), elev(.0)
|
||
, dLen(.0), dAng(.0), dBulge(.0), dOldLen(.0)
|
||
, d1(.0), d2(.0);
|
||
AcGePoint3d ptCurveEnd(AcGePoint3d::kOrigin)
|
||
, ptCurveStart(AcGePoint3d::kOrigin)
|
||
, ptOnCurve(AcGePoint3d::kOrigin)
|
||
, ptOnCenter(AcGePoint3d::kOrigin)
|
||
, pt(AcGePoint3d::kOrigin)
|
||
, pt1(AcGePoint3d::kOrigin)
|
||
, pt2(AcGePoint3d::kOrigin);
|
||
|
||
std::vector<std::pair<AcGePoint3d, CString>> insPts(0);
|
||
std::set<CString> setStakes;
|
||
CString strStake(_T(""));
|
||
|
||
pClonePoly->getStartPoint(ptCurveStart);
|
||
if (ptCurveStart.distanceTo(ptOrign) > 1e-7)
|
||
reverseCurve(pClonePoly);
|
||
|
||
AcGeCircArc3d arc;
|
||
AcGeLineSeg3d seg;
|
||
for (int i = 0; i < pClonePoly->numVerts() - 1; ++i)
|
||
{
|
||
pClonePoly->getBulgeAt(i, dBulge);
|
||
if (abs(dBulge) > 1e-7) // 弧
|
||
{
|
||
pClonePoly->getArcSegAt(i, arc);
|
||
dCurveLen = arc.length(arc.paramOf(arc.startPoint()), arc.paramOf(arc.endPoint()));
|
||
}
|
||
else
|
||
{
|
||
pClonePoly->getLineSegAt(i, seg);
|
||
dCurveLen = seg.length();
|
||
}
|
||
|
||
int j(0);
|
||
dLen = .0;
|
||
while (true)
|
||
{
|
||
pClonePoly->getPointAtDist(dLen + dOldLen, ptOnCurve);
|
||
ptOnCurve.z = .0;
|
||
getClosestPointTo(centerID, ptOnCurve, ptOnCenter);
|
||
if (!StakeTools::getDistByPointForCenterLine(ids, centerID, ptOnCenter, stakeDist))
|
||
{
|
||
acutPrintf(_T("\n提取桩号失败。"));
|
||
break;
|
||
}
|
||
if (!getElevationByStakeDist(stakeDist, mapStake, elev))
|
||
{
|
||
acutPrintf(_T("\n提取终点高程失败。"));
|
||
break;
|
||
}
|
||
|
||
ptOnCurve.z = elev;
|
||
strStake = StakeTools::generateStakeString(stakeDist, prefix);
|
||
|
||
//if (setStakes.insert(strStake).second)
|
||
if (insPts.empty())
|
||
insPts.push_back(std::make_pair(ptOnCurve, strStake));
|
||
else
|
||
{
|
||
if (insPts.rbegin()->first.distanceTo(ptOnCurve) > 1e-2)
|
||
insPts.push_back(std::make_pair(ptOnCurve, strStake));
|
||
}
|
||
|
||
if (EQUAL(dLen, dCurveLen)) break;
|
||
|
||
//if (insPts.size() > 1 && dLen < 1e-4)
|
||
//{
|
||
// // 判断最后两个点在curve间的距离
|
||
// pt1 = insPts[insPts.size() - 1].first;
|
||
// pt2 = insPts[insPts.size() - 2].first;
|
||
// pClonePoly->getDistAtPoint(pt1, d1);
|
||
// pClonePoly->getDistAtPoint(pt2, d2);
|
||
// if (EQUAL(abs(d2 - d1), dSpace))
|
||
// dLen += dSpace;
|
||
// else
|
||
// dLen += dSpace - abs(d2 - d1);
|
||
//}
|
||
//else
|
||
dLen += dSpace;
|
||
|
||
if (UP_ZERO(dLen - dCurveLen))
|
||
{
|
||
// 这里考虑了整段曲线长度小于dSpace的情况
|
||
if (j > 0)
|
||
insPts.pop_back();
|
||
dLen = dCurveLen;
|
||
}
|
||
j++;
|
||
}
|
||
dOldLen += dCurveLen;
|
||
}
|
||
DELETE_PTR(pClonePoly);
|
||
|
||
insert3dPoly(insPts);
|
||
}
|
||
|
||
void modifyGradient()
|
||
{
|
||
AcDbObjectIdArray idEws, idEwAll, idEwNexts, idEwPrevs;
|
||
|
||
GLTools::getConnectWorms(idEws, &idEwNexts, &idEwPrevs);
|
||
|
||
if (idEws.isEmpty()) return;
|
||
|
||
GetConnectedWorms(idEws[0], idEwAll);
|
||
|
||
double dG(.0);
|
||
if (acedGetReal(_T("\n请输入坡度百分比:"), &dG) != RTNORM) return;
|
||
|
||
double dPrevElev(.0), dNextElev(.0);
|
||
|
||
// 设置第一段管廊与前一段管廊的连接,再修改坡度
|
||
OPENOBJ_BEGIN(idEws.first(), AcDb::kForWrite, AecDbEarthWorm, pEw)
|
||
{
|
||
if (pEw && pEw->GetSegmentCount() > 0)
|
||
{
|
||
if (!idEwPrevs.isEmpty())
|
||
{
|
||
OPENOBJ_BEGIN(idEwPrevs.last(), AcDb::kForWrite, AecDbEarthWorm, pPrev)
|
||
{
|
||
if (pPrev)
|
||
{
|
||
pEw->SetLastDir(pPrev->GetTailDir());
|
||
pPrev->SetNextDir(pEw->GetHeadDir());
|
||
}
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
pEw->SetGradientAt(0, dG);
|
||
pEw->UpdateRoomDraw();
|
||
dPrevElev = pEw->GetTailElevation();
|
||
}
|
||
}
|
||
OPENOBJ_END()
|
||
|
||
// 然后从第二段开始,修改坡度,并与其前一段相连
|
||
for (size_t i = 1; i < idEws.length(); ++i)
|
||
{
|
||
OPENOBJ_BEGIN(idEws[i - 1], AcDb::kForWrite, AecDbEarthWorm, pPrev)
|
||
{
|
||
OPENOBJ_BEGIN(idEws[i], AcDb::kForWrite, AecDbEarthWorm, pEw)
|
||
{
|
||
if (pPrev && pEw && pEw->GetSegmentCount() > 0)
|
||
{
|
||
pEw->SetGradientAt(0, dG);
|
||
pEw->SetStartElevation(dPrevElev, false);
|
||
pEw->UpdateRoomDraw();
|
||
dPrevElev = pEw->GetTailElevation();
|
||
pEw->SetLastDir(pPrev->GetTailDir());
|
||
pPrev->SetNextDir(pEw->GetHeadDir());
|
||
}
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
|
||
// 设置下一段管廊的坡度
|
||
if (!idEwNexts.isEmpty())
|
||
{
|
||
OPENOBJ_BEGIN(idEwNexts.first(), AcDb::kForWrite, AecDbEarthWorm, pEw)
|
||
if (pEw)
|
||
{
|
||
dG = (pEw->EndElevation() - dPrevElev) / pEw->StartPoint().distanceTo(pEw->EndPoint()) * 100;
|
||
pEw->SetStartElevation(dPrevElev, false);
|
||
pEw->SetGradientAt(0, dG);
|
||
pEw->UpdateRoomDraw();
|
||
|
||
OPENOBJ_BEGIN(idEws.last(), AcDb::kForWrite, AecDbEarthWorm, pPrev)
|
||
{
|
||
if (pPrev)
|
||
{
|
||
pEw->SetLastDir(pPrev->GetTailDir());
|
||
pPrev->SetNextDir(pEw->GetHeadDir());
|
||
|
||
// 再与下一段连接
|
||
if (idEwNexts.length() > 2)
|
||
{
|
||
OPENOBJ_BEGIN(idEwNexts[1], AcDb::kForWrite, AecDbEarthWorm, pNext)
|
||
{
|
||
if (pNext)
|
||
{
|
||
pNext->SetLastDir(pEw->GetTailDir());
|
||
pEw->SetNextDir(pNext->GetHeadDir());
|
||
}
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
}
|
||
}
|
||
OPENOBJ_END()
|
||
|
||
}
|
||
OPENOBJ_END()
|
||
}
|
||
|
||
AcDbObjectIdArray arVIds;
|
||
CollectEarthwormForVSection(idEwAll, arVIds);
|
||
ContinueVerSection(arVIds, 1);
|
||
return;
|
||
}
|
||
|
||
void stretchEwByAngle()
|
||
{
|
||
ads_name ent;
|
||
ads_point pt;
|
||
AcDbObjectId idEw(AcDbObjectId::kNull), idPoly(AcDbObjectId::kNull);
|
||
|
||
int nRes = acedEntSel(_T("\n请选择上一段管廊:"), ent, pt);
|
||
if (nRes != RTNORM) return;
|
||
acdbGetObjectId(idEw, ent);
|
||
if (!GLTools::isThisClass<AecDbEarthWorm>(idEw))
|
||
{
|
||
acutPrintf(_T("\n选择的实体不是管廊!"));
|
||
return;
|
||
}
|
||
|
||
nRes = acedEntSel(_T("\n请选择道路中心线:"), ent, pt);
|
||
acdbGetObjectId(idPoly, ent);
|
||
if (!GLTools::isThisClass<AcDbPolyline>(idPoly))
|
||
{
|
||
acutPrintf(_T("\n选择的实体不是polyline!"));
|
||
return;
|
||
}
|
||
|
||
GripMessage msg;
|
||
msg.idHost = idEw;
|
||
msg.nType = kSegStretchDir;
|
||
|
||
// 用户输入角度,得到管廊结束桩号
|
||
double dAngle(45);
|
||
CString endStake(_T(""));
|
||
AcGePoint2d pt2dE(AcGePoint2d::kOrigin), pt2dS(AcGePoint2d::kOrigin);
|
||
|
||
OPENOBJ_BEGIN(idEw, AcDb::kForRead, AecDbEarthWorm, pEw)
|
||
if (!pEw) return;
|
||
pt2dE = pEw->EndPoint();
|
||
pt2dS = pEw->StartPoint();
|
||
acedGetReal(_T("\n请输入相对角度<45>:"), &dAngle);
|
||
dAngle = dAngle * PI / 180;
|
||
int segIdx = pEw->GetSegmentCount() - 1;
|
||
EWSegment seg;
|
||
pEw->GetSegment(segIdx, seg);
|
||
int subSegIdx = seg.nDeformationJoints - 1;
|
||
AcArray<EWFnctNode> arFncNodes;
|
||
pEw->GetFncNodeAt(segIdx, subSegIdx, arFncNodes);
|
||
if (arFncNodes.isEmpty())
|
||
pEw->GetStakeAt(segIdx, subSegIdx, endStake);
|
||
else
|
||
pEw->GetStakeAt(segIdx, subSegIdx, arFncNodes.length() - 1, endStake);
|
||
msg.nSegindex = pEw->GetSegmentCount();
|
||
msg.ptGrip.set(pt2dE.x, pt2dE.y, pEw->EndElevation());
|
||
OPENOBJ_END()
|
||
|
||
if (endStake.IsEmpty())
|
||
{
|
||
acutPrintf(_T("\n管廊末端桩号为空。"));
|
||
return;
|
||
}
|
||
|
||
// 收集所有上华桩号
|
||
std::vector<AcDbObjectId> idTxts(0);
|
||
StakeTools::getSHSStakeOfAll(idTxts, true);
|
||
|
||
AcDbRay ray;
|
||
getRay(idEw, ray, dAngle);
|
||
|
||
double dRot(.0);
|
||
AcDbObjectId idLeft(AcDbObjectId::kNull);
|
||
AcDbObjectId idStake = searchSHStakeByString(idTxts, endStake, idLeft);
|
||
AcDbXline xline;
|
||
getXline(idStake, idLeft, xline, idPoly, endStake);
|
||
|
||
#ifdef _DEBUG
|
||
AddToModelSpace((AcDbEntity*)ray.clone());
|
||
AddToModelSpace((AcDbEntity*)xline.clone());
|
||
#endif // _DEBUG
|
||
|
||
AcGePoint3dArray pts;
|
||
xline.intersectWith(&ray, AcDb::kOnBothOperands, AcGePlane::kXYPlane, pts);
|
||
if (pts.isEmpty())
|
||
{
|
||
acutPrintf(_T("\n角度方向与桩号延长线不相交。"));
|
||
return;
|
||
}
|
||
AcGeVector3d vt3d(pts[0] - AcGePoint3d(pt2dE.x, pt2dE.y, .0));
|
||
msg.vtOffset = vt3d;
|
||
msg.nSubSegIndex = 0;
|
||
_tcscpy(msg.szLockId, _T("End"));
|
||
PushGripMessage(msg);
|
||
|
||
#ifdef _DEBUG
|
||
AcDbCircle *pC = new AcDbCircle(pts[0], AcGeVector3d::kZAxis, 1);
|
||
AddToModelSpace(pC);
|
||
pC = new AcDbCircle(AcGePoint3d(pt2dS.x, pt2dS.y, 0), AcGeVector3d::kZAxis, 1);
|
||
AddToModelSpace(pC);
|
||
pC = new AcDbCircle(AcGePoint3d(pt2dE.x, pt2dE.y, 0), AcGeVector3d::kZAxis, 2);
|
||
AddToModelSpace(pC);
|
||
#endif // _DEBUG
|
||
}
|
||
|
||
|
||
void createSection(AcGePoint3d *pArr, int len, double R, double h)
|
||
{
|
||
AcGeVector3d vt(AcGeVector3d::kXAxis * R);
|
||
for (int i = 0; i < len; ++i)
|
||
{
|
||
vt = AcGeVector3d::kXAxis * R;
|
||
vt.rotateBy(i * (2*PI/len), AcGeVector3d::kZAxis);
|
||
pArr[i] = AcGePoint3d::kOrigin + vt;
|
||
pArr[i].z = h;
|
||
}
|
||
}
|
||
|
||
void ew_test()
|
||
{
|
||
}
|
||
}
|
||
|