#include "stdafx.h" #include "stdarx.h" #include #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 #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 &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> &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> &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 pts(0); std::vector 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 &a, std::pair &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 &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(id)) return id; if (GLTools::isThisClass(id)) return id; if (GLTools::isThisClass(id)) return id; id == AcDbObjectId::kNull; continue; } acedSSFree(ss); return id; } bool getAllStake(std::map &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 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 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_((LPCTSTR)sElev); // 直接就是桩号距离 if (StakeTools::IsDoubleString(sStake)) dDist = _convert_((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 &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::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 &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 &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 &bgss) { if (_taccess(szPath, 0x0) != 0x0) return false; CStdioFile file(szPath, CFile::shareDenyRead); if (!file.m_hFile) return false; CString strLine(_T("")); std::vector 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(refCurveID)) { acutPrintf(_T("\n选择的实体不是参照曲线。")); return; } nRes = acedEntSel(_T("\n请选择初始桩号<选择参照线起点>:"), adsName, adsPnt); if (nRes != RTNORM) return; acdbGetObjectId(StartTxtID, adsName); if (!GLTools::isThisClass(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> 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 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> 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(idStake)) { acutPrintf(_T("\n请选择一个文字对象。")); return; } nRes = acedEntSel(_T("\n请选择“地面高程”所在行的行头。"), name_ground, pt); if (nRes != RTNORM) return; acdbGetObjectId(idGround, name_ground); if (!GLTools::isThisClass(idGround)) { acutPrintf(_T("\n请选择一个文字对象。")); return; } nRes = acedEntSel(_T("\n请选择“设计高程”所在行的行头。"), name_design, pt); if (nRes != RTNORM) return; acdbGetObjectId(idDesign, name_design); if (!GLTools::isThisClass(idDesign)) { acutPrintf(_T("\n请选择一个文字对象。")); return; } // 收集所有模型空间内文字对象 std::vector ids(0); collectDbText(ids); // 去掉三个行头文字ID std::vector::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> 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> 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 vecs; std::map 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_((LPCTSTR)sElev); // 直接就是桩号距离 if (StakeTools::IsDoubleString(sStake)) dDist = _convert_((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 strSet; std::pair::iterator, bool> pr; CString sTxt(_T("")); AcGePoint3d ptTxt(AcGePoint3d::kOrigin); double d; AcDbObjectId id; Adesk::Int32 lLen = 0L; acedSSLength(ss,&lLen); std::vector> pts(0); AcString str; std::map 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::iterator it = mapStake.begin(); std::map::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> 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(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(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(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(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(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(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 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(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 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(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, GLTools::compare_double> mapPt; std::vector stakes(0); STakeInfo info; std::set setStr; std::pair::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(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> 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 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(centerID)) { acutPrintf(_T("\n所选对象不是曲线对象。")); return; } nRes = acedEntSel(_T("\n请选择一条polyline做为管廊的走向。"), adsEnt, adsPt); if (nRes != RTNORM) return; acdbGetObjectId(polyID, adsEnt); if (!GLTools::isThisClass(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> insPts(0); std::set 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(idEw)) { acutPrintf(_T("\n选择的实体不是管廊!")); return; } nRes = acedEntSel(_T("\n请选择道路中心线:"), ent, pt); acdbGetObjectId(idPoly, ent); if (!GLTools::isThisClass(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 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 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() { } }