#include "stdafx.h" #include "LandScapeStyle.h" #include #include "symdef.h" #include "geplanar.h" #include "DrawRoadDlg.h" // 引入绘制道路对话框头文件 #include "TRoadDragJig.h" #include "RoadFillterMgr.h" #include "TlandScapeDragjig.h" #include "TDbRoadEntity.h" #include "LandScapeStyle.h" #include "GlwGlobalVariable.h" #include using namespace RoadDrag; //Class LandScapeEntity CLandScapeStyle::CLandScapeStyle():m_dArcRad(6000), m_dRoadWidth(1000),m_dWidthPercent(80),m_bRoadLine(FALSE), m_bAutoAdjust(FALSE),m_nDrawType(1),m_dgap(200), m_bIsUnitPercent(FALSE) { } CLandScapeStyle::~CLandScapeStyle() { } extern BOOL DragPolyLine(AcDbPolyline *pLine, XPoint ptStart); //获取指定图层上所有实体ID AcDbObjectIdArray GetAllEntityId(const TCHAR* layername) { AcDbObjectIdArray entIds; bool bFilterlayer = false; AcDbObjectId layerId; //获取指定图层对象ID if (layername != NULL) { AcDbLayerTable *pLayerTbl = NULL; acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTbl, AcDb::kForRead); if (!pLayerTbl->has(layername)) { pLayerTbl->close(); return entIds; } pLayerTbl->getAt(layername, layerId); pLayerTbl->close(); bFilterlayer = true; } //获得块表 AcDbBlockTable *pBlkTbl = NULL; acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlkTbl, AcDb::kForRead); //块表记录 AcDbBlockTableRecord *pBlkTblRcd = NULL; pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForRead); pBlkTbl->close(); //创建遍历器,依次访问模型空间中的每一个实体 AcDbBlockTableRecordIterator *it = NULL; pBlkTblRcd->newIterator(it); for (it->start(); !it->done(); it->step()) { AcDbEntity *pEnt = NULL; Acad::ErrorStatus es = it->getEntity(pEnt, AcDb::kForRead); if (es == Acad::eOk) { if (bFilterlayer)//过滤图层 { if (pEnt->layerId() == layerId) { entIds.append(pEnt->objectId()); } } pEnt->close(); } } delete it; pBlkTblRcd->close(); return entIds; } BOOL Joinjudge(AcDbPolyline &polyLine) { AcDbObjectIdArray allEntIds = GetAllEntityId(LAY_LSCP_ROAD); AcDbObjectId blkRefId; AcDbBlockReference *pBlkRef = NULL; AcGePoint3dArray pt; for (int i = 0; i < allEntIds.length(); i++) { if (acdbOpenObject(pBlkRef, allEntIds[i], AcDb::kForRead) == Acad::eOk) { if (acdbOpenObject(pBlkRef, blkRefId, AcDb::kForRead) == Acad::eOk) { for (int j = 0; j < allEntIds.length(); j++) { if (allEntIds[j] != blkRefId) { if (acdbOpenObject(pBlkRef, allEntIds[j], AcDb::kForRead) == Acad::eOk) { polyLine.intersectWith(pBlkRef, AcDb::kOnBothOperands, pt, 0, 0); if (!pt.isEmpty()) { pBlkRef->erase(); } } } } } } } return TRUE; } bool DrawRoadLine(AcDbPolyline &polyLine, double dRoadWidth, bool bDrawRoadLine) { //判断是否绘制路边线,不绘制直接返回。 XPoly2D poly2dLeft, poly2dRight; PolyConvert(polyLine, poly2dLeft); PolyConvert(polyLine, poly2dRight); if (!Offset(-dRoadWidth / 2.0, poly2dLeft)) { adsout << _T("\n所选线段不支持向左偏移!"); return false; } if (!Offset(dRoadWidth / 2.0, poly2dRight)) { adsout << _T("\n所选线段不支持向右偏移!"); return false; } AcDbPolyline *pRoadLineLeft = new AcDbPolyline(); if (pRoadLineLeft == NULL) return false; PolyConvert(poly2dLeft, *pRoadLineLeft); AcDbPolyline *pRoadLineRight = new AcDbPolyline(); if (pRoadLineRight == NULL) { delete pRoadLineLeft; return false; } PolyConvert(poly2dRight, *pRoadLineRight); if (!bDrawRoadLine) { pRoadLineLeft->setVisibility(AcDb::kInvisible); pRoadLineRight->setVisibility(AcDb::kInvisible); } AddToModelSpace(pRoadLineLeft, Adesk::kTrue); AddToModelSpace(pRoadLineRight, Adesk::kTrue); return true; } BOOL CLandScapeStyle::selectPath() { PickSet ss(SS_FREE);//选择集 std::vector vecPtAndAngle;//点和角度 RBList rbMask(RTDXF0, _T("LINE,ARC,POLYLINE,LWPOLYLINE,CIRCLE"), NULL); while (1) { int nRet = SelectEntities(_T("\n请选择作为路径的曲线(线/圆/弧/多段线) <退出>:"), ss, rbMask); if (nRet != RTNORM) { return false; } DataUpdate(); std::vector Angle ; double dAngle(0.0); long ni = 0, nSsLen = ss.Length(); AcGePoint3dArray arPts;// 保存插入点 // 打开选择集中的实体 for (ni = 0; ni < nSsLen; ni++) { OPENOBJ_BEGIN(ss[ni], AcDb::kForWrite, AcDbEntity, pEnt); if (pEnt->isKindOf(AcDbLine::desc())) // 直线 { AcDbLine* pLine = AcDbLine::cast(pEnt); DrawLineRoad(pLine); } else if (pEnt->isKindOf(AcDbArc::desc()))// 圆弧 { AcDbArc *pArc = AcDbArc::cast(pEnt); DrawArcRoad(pArc); } else if (pEnt->isKindOf(AcDbPolyline::desc()))// 多段线,起点位置 { AcDbPolyline *pPolyLine = AcDbPolyline::cast(pEnt); DrawPolyRoad(pPolyLine); } else if (pEnt->isKindOf(AcDbCircle::desc()))//圆 { AcDbCircle *pCircle = AcDbCircle::cast(pEnt); AcDbPolyline *pPline = new AcDbPolyline(3); pPline->setPropertiesFrom(pEnt); // 设置属性 AcGePoint3d ptCenter = pCircle->center(); double dRadius = ((AcDbCircle*)pEnt)->radius(); pPline->addVertexAt(0, AcGePoint2d(ptCenter.x + dRadius, ptCenter.y), 1); pPline->addVertexAt(1, AcGePoint2d(ptCenter.x - dRadius, ptCenter.y), 1); pPline->addVertexAt(2, AcGePoint2d(ptCenter.x + dRadius, ptCenter.y), 1); DrawPolyRoad(pPline); delete pPline; } pEnt->erase(true); OPENOBJ_END(); } } return TRUE; } CLandScapeStateData* ConLandScapeStateClass(TLandScapeDragContext::ESequence eSequence, TlandScapeDragjig *pJig, TLandScapeDragContext *pContex) { switch (eSequence) { case TLandScapeDragContext::eFirstIn: return new CLandScapeFirstInState(pJig, pContex); break; case TLandScapeDragContext::eLineRoad: return new CLineLandScapeState(pJig, pContex); break; case TLandScapeDragContext::eNextLineRoad: return new CNextLineLandScapeState(pJig, pContex); break; case TLandScapeDragContext::eThirdLineRoad: return new CThirdLineLandScapeState(pJig, pContex); break; case TLandScapeDragContext::eArcRoad: return new CArcLandScapeState(pJig, pContex); break; case TLandScapeDragContext::eNextArcRoad: return new CNextArcLandScapeState(pJig, pContex); break; case TLandScapeDragContext::eArcMidRoad: return new CMidArcLandScapeState(pJig, pContex); break; case TLandScapeDragContext::eArcRad: return new CArcRadLandScapeState(pJig, pContex); break; default: return NULL; break; } } BOOL CLandScapeStyle::dynamicDraw() { // jig负责控制实时显示 TlandScapeDragjig jig(this); // 道路手工绘制时,保存的上下文,以及一些相关数据 TLandScapeDragContext context(this); // 道路绘制状态类,供jig调用 CLandScapeStateData *pState = NULL; CLandScapeStyle* pLandScape = GET_GLOBAL_VARIABLE(CLandScapeStyle); BOOL bFirst = FALSE, bCancel = FALSE; while (context.GetSequenceState() != TLandScapeDragContext::eSequenceCancel && context.GetSequenceState() != TLandScapeDragContext::eSequenceOk) { ASSERT(pState == NULL); if (context.GetSequenceState() == TLandScapeDragContext::eFirstIn) bFirst = TRUE; else bFirst = FALSE; pState = ConLandScapeStateClass(context.GetSequenceState(), &jig, &context); jig.SetState(pState); jig.DoIt(); delete pState; pState = NULL; if (context.GetSequenceState() == TLandScapeDragContext::eSequenceCancel) bCancel = TRUE; else bCancel = FALSE; if (bFirst&&bCancel) return FALSE; if (context.GetSequenceState() == TLandScapeDragContext::eSequenceCancel) context.SetSequenceState(TLandScapeDragContext::eFirstIn); } return FALSE; } void CLandScapeStyle::SetDlgData(const double dRoadWidth, double dRoadWidthMM, double dWidthPercent, const double dgap, const AcDbObjectId obj, BOOL bRodeLine, const BOOL bAutoAdjust, const double dBlockWidth, const double dBlockHeight, const double dRealBlockWidth, BOOL bIsUnitPercent) { m_dRoadWidth = dRoadWidth; m_dWidthPercent = dWidthPercent; m_dgap = dgap; m_idObj = obj; m_bRoadLine = bRodeLine; m_bAutoAdjust = bAutoAdjust; m_dBlockLen = dBlockHeight; m_dBlockWidth = dBlockWidth; m_dRealBlockWidth = dRealBlockWidth; m_bIsUnitPercent = bIsUnitPercent; } int CLandScapeStyle::GetRealGapOnLine(AcGePoint3d ptStart, AcGePoint3d ptEnd) { DataUpdate(); m_dRealBlockLen = (m_dRealBlockWidth / m_dBlockWidth) * m_dBlockLen;//获取真实图块长度 double dLen = ptStart.distanceTo(ptEnd);//长度 int iNum; double dDist; if (m_bAutoAdjust)//自调勾选 { iNum = (dLen - m_dRealBlockLen) / (m_dgap + m_dRealBlockLen);//图块个数 double dTrueGap = (dLen - m_dRealBlockLen) / iNum - m_dRealBlockLen;//图块实际间距 m_dRealGap = dTrueGap; } else { dDist = (dLen) / (m_dgap + m_dRealBlockLen); iNum = dDist; double dDistLen = dLen - iNum * (m_dgap + m_dRealBlockLen);//计算剩余的长度 if (dDistLen >= (m_dRealBlockLen))//判断剩余的长度够不够再画一个图块 ++iNum; m_dRealGap = m_dgap; } return iNum; } void CLandScapeStyle::setPointAt(XPoint pt) { /*m_ptEnd = pt;*/ } bool CLandScapeStyle::MakeBlockReference(AcGePoint3d ptInsert, double dAngle) { DataUpdate(); AcDbBlockReference *pRef = new AcDbBlockReference(ptInsert, m_idObj); if (pRef == NULL) { delete pRef; return false; } AcDbExtents extents; AcGePoint3d ptLow, ptUp; // 获得块的包围盒 pRef->getGeomExtents(extents); // 计算块的大小 ptLow = extents.minPoint(); ptUp = extents.maxPoint(); double dSizey = (ptUp.y - ptLow.y); // 比例变化矩阵 AcGeMatrix3d xform; // 设置块比例 xform.setToScaling(m_dRealBlockWidth / dSizey, ptInsert); pRef->transformBy(xform); //设置块旋转角度 xform.setToRotation(dAngle, AcGeVector3d::kZAxis, ptInsert); pRef->transformBy(xform); //设置图层 AcDbObjectId idLayer = InitLayer(LAY_LSCP_ROAD); pRef->setLayer(idLayer); AddToModelSpace(pRef, Adesk::kTrue); // 添加到数据库中 return true; } BOOL CLandScapeStyle::DataUpdate() { //对话框数据实时更新 if (CDrawLandScapeDlg::g_pCurDlg != NULL && IsWindow(CDrawLandScapeDlg::g_pCurDlg->m_hWnd)) { m_bAutoAdjust = CDrawLandScapeDlg::g_pCurDlg->GetAutoAdjustState(); m_dBlockLen = CDrawLandScapeDlg::g_pCurDlg->GetBlockLen(); m_dBlockWidth = CDrawLandScapeDlg::g_pCurDlg->GetBlockWidth(); m_dgap = CDrawLandScapeDlg::g_pCurDlg->GetGap(); m_idObj = CDrawLandScapeDlg::g_pCurDlg->GetLandScapeId(); m_dRoadWidth = _AS_MM(CDrawLandScapeDlg::g_pCurDlg->GetRoadWidth()); m_bRoadLine = CDrawLandScapeDlg::g_pCurDlg->GetRoadLineState(); m_dRealBlockWidth = CDrawLandScapeDlg::g_pCurDlg->GetUnitRealWidth(); m_dWidthPercent = CDrawLandScapeDlg::g_pCurDlg->GetWidthPercent(); return TRUE; } else return FALSE; } void CLandScapeStyle::LineStyle(AcDbLine *pLine, double dGap, BOOL bAutoAdjust, std::vector& vecPtAndAngle) { PointAndAngle temp; // 获得直线的起点和终点 AcGePoint3d ptSt, ptEnd, ptInsertNew; XPoint ptInsert; ptSt = pLine->startPoint(); ptEnd = pLine->endPoint(); vecPtAndAngle.clear(); // 计算直线的长度 double dLenth = ptSt.distanceTo(ptEnd); AcGeVector3d ver = ptEnd - ptSt; // 当前的坐标系 double dUcsAngle = 0.0; AcGeVector3d vtCur(cos(dUcsAngle), sin(dUcsAngle), 0); // 生成块的数量 int iNum = 0; iNum = GetRealGapOnLine(ptSt, ptEnd); dUcsAngle = ver.angleTo(vtCur, AcGeVector3d::kZAxis); if (dLenth > m_dRealBlockLen) { acutPolar(XPoint(ptSt), -dUcsAngle, m_dRealBlockLen / 2, ptInsert); temp.ptPoint = ptInsert; temp.dAngle = dUcsAngle; vecPtAndAngle.push_back(temp);// 在 起点 插入块 } if (dLenth > 2 * m_dRealBlockLen) { if (m_bAutoAdjust) { acutPolar(XPoint(ptEnd), -dUcsAngle, -m_dRealBlockLen / 2, ptInsert); temp.ptPoint = ptInsert; temp.dAngle = dUcsAngle; vecPtAndAngle.push_back(temp);//在 终点 插入块 } } iNum--; m_dRealBlockLen = (m_dRealBlockWidth / m_dBlockWidth) * m_dBlockLen;//获取真实图块长度 for (int i = 0; i < iNum; i++) { // 计算新的插入点 acutPolar(asDblArray(ptSt), -dUcsAngle, (m_dRealGap + m_dRealBlockLen * 3 / 2) + (m_dRealGap + m_dRealBlockLen) * i, asDblArray(ptInsertNew)); temp.ptPoint = ptInsertNew; temp.dAngle = dUcsAngle; vecPtAndAngle.push_back(temp); } } void CLandScapeStyle::ArcStyle(AcDbArc *pArc, double dGap, double dBugle, BOOL bAutoAdjust, std::vector& vecPtAndAngle) { vecPtAndAngle.clear(); PointAndAngle temp; AcGePoint3d ptStart, ptCentre, ptEnd; // 获得圆弧的参数 pArc->getStartPoint(ptStart); ptCentre = pArc->center(); pArc->getEndPoint(ptEnd); double dArcRad = pArc->radius(); // 计算弧长 double dLenth = (pArc->endAngle() - pArc->startAngle()) * dArcRad; if (dLenth < 0 + _DIST_SNAP)// 优弧 { dLenth = 2 * PI * dArcRad + dLenth; } // 当前的坐标系 double dUcsAngle(0.0); // 生成块的数量 int iNum = 0; GetRealBlockLen();//获取真实图块长度 AcGePoint3d ptStartNew, ptInsert; AcGeVector3d verSt, verEnd; double dAngleNew = (m_dRealBlockLen / 2) / dArcRad; verSt = ptStart - ptCentre; if (dBugle > -1E-6) verEnd = verSt.rotateBy(dAngleNew, AcGeVector3d::kZAxis); else verEnd = verSt.rotateBy(-dAngleNew, AcGeVector3d::kZAxis); ptStartNew = verEnd + ptCentre; double angle = ads_angle(XPoint(ptStartNew), XPoint(ptCentre)); angle -= PI / 2; temp.ptPoint = ptStartNew; temp.dAngle = -angle; vecPtAndAngle.push_back(temp); if (1/*bAutoAdjust*/)// 间距自调 { iNum = (dLenth - m_dRealBlockLen) / (m_dgap + m_dRealBlockLen);//图块个数 dGap = (dLenth - m_dRealBlockLen) / iNum - m_dRealBlockLen;//图块实际间距 // 根据弧长计算角度 dUcsAngle = (dGap+ m_dRealBlockLen ) / dArcRad; } else { // 根据弧长计算角度 dUcsAngle = (dGap + m_dRealBlockLen) / dArcRad; // 计算插入的数量 iNum = (int)(dLenth / (dUcsAngle*dArcRad)); } // verSt = ptStartNew - ptCentre; // 绘制 for (int i = 0; i-1E-6) { verEnd = verSt.rotateBy(dUcsAngle, AcGeVector3d::kZAxis); } else { verEnd = verSt.rotateBy(-dUcsAngle, AcGeVector3d::kZAxis); } ptInsert = verEnd + ptCentre; angle = ads_angle(XPoint(ptInsert), XPoint(ptCentre)); angle -= PI / 2; temp.dAngle = -angle; temp.ptPoint = ptInsert; vecPtAndAngle.push_back(temp); } } void CLandScapeStyle::PolyLineStyle(AcDbPolyline *pPolyLine, double dGap, BOOL bAutoAdjust, std::vector& vecPtAndAngle, AcGePoint3dArray &ptAryInsert) { // 获得多段线的起点,z终点 AcGePoint3d ptSt, ptEnd; pPolyLine->getStartPoint(ptSt); pPolyLine->getEndPoint(ptEnd); std::vector vecPtAndAngleTemp; // 获得多段线的所有顶点 int iNumVerts = pPolyLine->numVerts(); double dBulge = 0.0; AcGeCircArc3d arc; AcGeLineSeg3d line; AcGePoint3dArray aryTemp; for (int i = 0; i < iNumVerts - 1; i++) { // 获得顶点处的弧度值 pPolyLine->getBulgeAt(i, dBulge); if (dBulge != 0)// 圆弧 { pPolyLine->getArcSegAt(i, arc); // 获得几何图形的参数 AcGePoint3d ptCenter = arc.center(); AcGeVector3d normal = arc.normal(); AcGeVector3d refVec = arc.refVec(); AcGePlane plane = AcGePlane(ptCenter, normal); double dAng = refVec.angleOnPlane(plane); // 构造数据库的实体 AcDbArc *pArc = new AcDbArc(ptCenter, normal, arc.radius(), arc.startAng() + dAng, arc.endAng() + dAng); ArcStyle(pArc, dGap, dBulge, bAutoAdjust, vecPtAndAngleTemp); } else// 直线 { pPolyLine->getLineSegAt(i, line); AcDbLine *pLine = new AcDbLine(line.startPoint(), line.endPoint()); LineStyle(pLine, dGap, m_bAutoAdjust, vecPtAndAngleTemp); } ptAryInsert.append(aryTemp); vecPtAndAngle.insert(vecPtAndAngle.begin(), vecPtAndAngleTemp.begin(), vecPtAndAngleTemp.end()); } } //绘制直道 void CLandScapeStyle::DrawLineRoad(AcDbLine* pLine) { TLandScapeDragContext context(this); TDbLineLandScapeEntity* pLineRoad = new TDbLineLandScapeEntity(); pLineRoad->SetLineRoad(POINT_3D_TO_2D(pLine->startPoint()), POINT_3D_TO_2D(pLine->endPoint()), this); context.AddLineRoad(pLineRoad); delete pLineRoad; } //绘制弧道 void CLandScapeStyle::DrawArcRoad(AcDbArc* pArc) { AcGePoint3d ptStart, ptEnd, ptThird; pArc->getStartPoint(ptStart); pArc->getEndPoint(ptEnd); TLandScapeDragContext context(this); pArc->getPointAtDist(0.5 * (ptStart.distanceTo(ptEnd)), ptThird); TDbArcLandScapeEntity* pArcRoad = new TDbArcLandScapeEntity(); pArcRoad->SetArcRoad(POINT_3D_TO_2D(ptStart), POINT_3D_TO_2D(ptThird), POINT_3D_TO_2D(ptEnd), this); context.AddArcRoad(pArcRoad); delete pArcRoad; } void CLandScapeStyle::DrawPolyRoad(AcDbPolyline* pPoly) { CLandScapeStyle* pLandScape = GET_GLOBAL_VARIABLE(CLandScapeStyle); int iNumVerts = pPoly->numVerts(); double dBulge = 0.0; AcGeCircArc3d arc; AcGeLineSeg3d line; AcGePoint3dArray aryTemp; for (int i = 0; i < iNumVerts - 1; i++) { // 获得顶点处的弧度值 pPoly->getBulgeAt(i, dBulge); if (dBulge != 0)// 圆弧 { pPoly->getArcSegAt(i, arc); // 获得几何图形的参数 AcGePoint3d ptCenter = arc.center(); AcGeVector3d normal = arc.normal(); AcGeVector3d refVec = arc.refVec(); AcGePlane plane = AcGePlane(ptCenter, normal); double dAng = refVec.angleOnPlane(plane); double dAngSt = arc.startAng(); double dAngEnd = arc.endAng(); // 构造数据库的实体 AcDbArc *pArc = new AcDbArc(ptCenter, normal, arc.radius(), arc.startAng() + dAng, arc.endAng() + dAng); DrawArcRoad(pArc); delete pArc; } else// 直线 { pPoly->getLineSegAt(i, line); AcDbLine *pLine = new AcDbLine(line.startPoint(), line.endPoint()); DrawLineRoad(pLine); delete pLine; } } } AcDbObjectId CLandScapeStyle::MakeUnnamedGroup() { Acad::ErrorStatus es; AcDbObjectId groupobjId; AcDbGroup *pGroup = NULL; AcDbDictionary *pGroupDict = NULL; es = acdbCurDwg()->getGroupDictionary(pGroupDict,AcDb::kForWrite); if (es != Acad::eOk) { return NULL; } //新建一组,并添入字典 pGroup = new AcDbGroup; pGroup->setSelectable(Adesk::kTrue); es = pGroupDict->setAt(_T("*U"),pGroup,groupobjId); assert(es == Acad::eOk); pGroupDict->close(); //往组中添加选择集中的实体 AcDbObjectId objectId; long nLen = ssAll.Length(); for (long i = 0L;i < nLen;i++) { TEntitySet en = ssAll[i]; if (acdbGetObjectId(objectId,en) != Acad::eOk) { pGroup->close(); return NULL; } if (pGroup->append(objectId) != Acad::eOk) { pGroup->close(); return NULL; } } pGroup->close(); return groupobjId; }