/******************************************************************** created: 2004/03/09 created: 9:3:2004 10:22 filename: f:\tg_dev\telecdev\twtkernal\road.cpp file path: f:\tg_dev\telecdev\twtkernal file base: road file ext: cpp author: 沈睿 purpose: 道路绘制 *********************************************************************/ #include "stdafx.h" #include "tapi.h" #include "troadjig.h" //得到双线系统的2个线段 BOOL GetRoad2LineByPt(Entity entBase, Entity &ent1, Entity &ent2, XPoint ptBase) { RBList rbMask = ads_buildlist( -4, _T(""), -4, _T(""), -4, _T("or>"), NULL); CString csWidth; csWidth = ReadXdata(entBase, _T("ROADWIDTH")); double nWidth = _tstof(csWidth); XLine line(entBase, 1); XPoint ptTmp1, ptTmp2; double nAng = line.Direction(); XPoint ptUcs = Wcs2Ucs(ptBase); ads_polar(ptUcs, nAng + PI/2, nWidth/2+50, ptTmp1); ads_polar(ptUcs, nAng - PI/2, nWidth/2+50, ptTmp2); PickSet ss(SS_FREE); struct resbuf *pointlist; pointlist = ads_buildlist(RTPOINT, &ptTmp1, RTPOINT, &ptTmp2, NULL); ss.Get(_T("F"), pointlist, NULL, rbMask); ads_relrb(pointlist); long len = ss.Length(); // ss.Redraw(3); if(ss.Length() != 2) return FALSE; ent1 = ss[0L]; ent2 = ss[1L]; return TRUE; } //3通道路相连时,要进行打断/FILLET处理 void TrimFillet3Road(Entity ent1, Entity ent2, Entity ent3, Entity ent4, double nFilletRad) { XPoint ptInt1, ptInt2; //line1, line2是刚绘制的道路2线 XLine line1(ent1, LS_FINITE); XLine line2(ent2, LS_FINITE); //line3, line4是已经绘制的道路2线 XLine line3(ent3, LS_FINITE); XLine line4(ent4, LS_FINITE); //4条线均为 _T("LS_FINITE") 有限长, 目的是求线上交点, 而不是延长线交点 line1.SetLineFlag(1); line2.SetLineFlag(1); line3.SetLineFlag(1); line4.SetLineFlag(1); int ret1 = line3.Intersection(&line1, ptInt1); int ret2 = line3.Intersection(&line2, ptInt2); Entity entBre1, entBre2; if(ret1 == 1 && ret2 == 1){ BreakEntity(ent3, Wcs2Ucs(ptInt1), Wcs2Ucs(ptInt2)); entBre1 = ent3; } else if(ret1 == 0 && ret2 == 0){ ret1 = line4.Intersection(&line1, ptInt1); ret2 = line4.Intersection(&line2, ptInt2); if(ret1 == 1 && ret2 == 1){ BreakEntity(ent4, Wcs2Ucs(ptInt1), Wcs2Ucs(ptInt2)); entBre1 = ent4; } else return; } else return; entBre2.GetLast(); XLine line5(entBre1, LS_FINITE); XLine line6(entBre2, LS_FINITE); line5.SetLineFlag(1); line6.SetLineFlag(1); ret1 = line1.Intersection(&line5, ptInt1); ret2 = line1.Intersection(&line6, ptInt2); if(ret1 == 1 && ret2 == 0) FilletEntity(entBre1, ent1, nFilletRad); else if(ret1 == 0 && ret2 == 1) FilletEntity(entBre2, ent1, nFilletRad); ret1 = line2.Intersection(&line5, ptInt1); ret2 = line2.Intersection(&line6, ptInt2); if(ret1 == 1 && ret2 == 0) FilletEntity(entBre1, ent2, nFilletRad); else if(ret1 == 0 && ret2 == 1) FilletEntity(entBre2, ent2, nFilletRad); } //道路相连时,要进行FILLET处理 void FilletNextRoad(Entity ent1, Entity ent2, Entity ent3, Entity ent4, double nFilletRad) { XPoint ptInt; //line1, line2是刚绘制的道路2线 XLine line1(ent1, LS_FINITE); XLine line2(ent2, LS_FINITE); //line3, line4是已经绘制的道路2线 XLine line3(ent3, LS_FINITE); XLine line4(ent4, LS_FINITE); //4条线均为 _T("LS_FINITE") 有限长, 目的是求线上交点, 而不是延长线交点 line1.SetLineFlag(1); line2.SetLineFlag(1); line3.SetLineFlag(1); line4.SetLineFlag(1); BOOL bFlag = FALSE; BOOL bBreak = TRUE; int iIntersecton(-1); int ret1 = line1.Intersection(&line3, ptInt); int ret2 = line1.Intersection(&line4, ptInt); if(ret1 == 1 && ret2 == 0){ iIntersecton = 1; bFlag = FALSE; } else if(ret1 == 0 && ret2 == 1){ iIntersecton = 2; bFlag = TRUE; } else if(ret1 == 0 && ret2 == 0){ ret1 = line2.Intersection(&line3, ptInt); ret2 = line2.Intersection(&line4, ptInt); if(ret1 == 1 && ret2 == 0){ iIntersecton = 3; bFlag = TRUE; } else if(ret1 == 0 && ret2 == 1){ iIntersecton = 4; bFlag = FALSE; } else bBreak = FALSE;//2道路宽度不等时(4根线没有交点), 不需要做FILLET处理 } //4条线必然有2条线已经相交, 他们是一对, 另外2个是一对 if(bFlag && bBreak){ if(iIntersecton == 3) FilletEntity(ent2, ent3, nFilletRad); else FilletEntity(ent2, ent3, 0); if(iIntersecton == 2) FilletEntity(ent1, ent4, nFilletRad); else FilletEntity(ent1, ent4, 0); } else if(!bFlag && bBreak){ if(iIntersecton == 1) FilletEntity(ent1, ent3, nFilletRad); else FilletEntity(ent1, ent3, 0); if(iIntersecton == 4) FilletEntity(ent2, ent4, nFilletRad); else FilletEntity(ent2, ent4, 0); } } //打断相交的道路 void TrimInterRoad(Entity entLast, Entity ent1, Entity ent2, double nFilletRad) { RBList rbMask(RTDXF0, _T("LINE"), 8, LAY_TWT_DOTE, NULL); XLine line(entLast, 1); line.SetLineFlag(1); XPoint pt1Ucs, pt2Ucs; pt1Ucs = Wcs2Ucs(line.GetStartPoint()); pt2Ucs = Wcs2Ucs(line.GetEndPoint()); PickSet ss(SS_FREE); struct resbuf *pointlist; pointlist = ads_buildlist(RTPOINT, &pt1Ucs, RTPOINT, &pt2Ucs, NULL); ss.Get(_T("F"), pointlist, NULL, rbMask); ads_relrb(pointlist); if(ss.Length() == 0) return; long len = ss.Length(); for(long i=0;i nWidth || nDist2 > nWidth) //交点离起始点太远 return; BreakEntity(entIntRoad1, ptInt1, ptInt2); //TRIM, 打断新道路中间的部分 Entity entTmp; entTmp.GetLast(); XLine lRoadInt1(entIntRoad1, 1); XLine lRoadInt2(entTmp, 1); lRoadInt1.SetLineFlag(1); lRoadInt2.SetLineFlag(1); ret1 = lRoad1.Intersection(&lRoadInt1, ptInt1); //FILLET ret2 = lRoad1.Intersection(&lRoadInt2, ptInt2); if(ret1 == 1 && ret2 == 0) FilletEntity(ent1, entIntRoad1, nFilletRad); else if(ret1 == 0 && ret2 == 1) FilletEntity(ent1, entTmp, nFilletRad); ret1 = lRoad2.Intersection(&lRoadInt1, ptInt1); ret2 = lRoad2.Intersection(&lRoadInt2, ptInt2); if(ret1 == 1 && ret2 == 0) FilletEntity(ent2, entIntRoad1, nFilletRad); else if(ret1 == 0 && ret2 == 1) FilletEntity(ent2, entTmp, nFilletRad); } else{ //接拐弯道路 XLine lRoadInt1(entIntRoad1, 1); XLine lRoadInt2(entIntRoad2, 1); lRoadInt1.SetLineFlag(1); lRoadInt2.SetLineFlag(1); XPoint ptInt1, ptInt2; int ret1 = lRoad1.Intersection(&lRoadInt1, ptInt1); int ret2 = lRoad2.Intersection(&lRoadInt2, ptInt2); double nDist1 = ads_distance(ptInt1, ptStart); double nDist2 = ads_distance(ptInt2, ptStart); if(nDist1 > nWidth || nDist2 > nWidth) //交点离起始点太远 return; FilletEntity(ent1, entIntRoad1, nFilletRad); FilletEntity(ent2, entIntRoad2, nFilletRad); } } ///////////////////////////////////////////////////////////////////////////////////// // 绘制道路 // 要考虑的情况: // 1 连续绘制, 处理好前后交点 // A 道路变宽 B 道路内侧(有交点的2边)倒圆角 // 2 穿过别的道路, 4通倒圆角 // 3 起点在另外道路的端点 // 4 终点在另外道路的端点 // 5 起点在另外道路的中间, 生成3通 // 6 终点在另外道路的中间, 生成3通 // 7 起点在3通处, 生成4通 // 8 终点在3通处, 生成4通 ///////////////////////////////////////////////////////////////////////////////////// void DrawRoad() { int nOsMode=0; xg_getvar(_T("OSMODE"), &nOsMode); nOsMode &= ~0x4000; nOsMode |= OS_INT|OS_NEA|OS_PER|OS_END; XPushVar vOsMode(_T("OSMODE"), nOsMode); XPoint ptStart, ptEnd; Entity entLast, ent1, ent2, ent3, ent4, entBase; ads_getpoint(NULL, _T("\n请点取道路起点<退出>"), ptStart); ptStart = Ucs2Wcs(ptStart); xg_setvar(_T("FilletRad"), 0); int num = GetBaseRoadByPt(ptStart, Entity(), entBase); double nRoadWidth = 60 * DocGetPScale(); //道路宽度 6米 InitLayer(LAY_TWT_ROAD); InitLayer(LAY_TWT_DOTE); double nDist(0), nFilletRad(nRoadWidth); CRegProperty regProp(GetRegLocation(), _T("TWTConfig")); regProp.SetTopRootKey(HKEY_CURRENT_USER); regProp.GetValue(_T("FilletRad"), nRoadWidth); regProp.GetValue(_T("RoadWidth"), nFilletRad); if(DocGetPScale() < 5 && nRoadWidth > 1000 && nFilletRad > 1000){ nRoadWidth = nRoadWidth/100; nFilletRad = nFilletRad/100; } XPushVarStr clayer(_T("CLAYER"), LAY_TWT_ROAD); while(1){ TRoadJig jig(ptStart, nRoadWidth); jig.SetPrompt(_T("\n请输入终点[路宽(W)/路长(A)/倒角半径(R)]<退出>:")); int nKeyIndex; jig.m_nDist = nDist; jig.SetKeyword(_T("W A R")); int ret = jig.DoIt(&nKeyIndex); if(ret == RTKWORD){ CString csPrompt; csPrompt.Format(_T("\n请输入道路的宽度<%.0f>:"), nRoadWidth); if(nKeyIndex == 0) ads_getdist(ptStart, csPrompt, &nRoadWidth); else if(nKeyIndex == 1){ int ret0 = ads_getdist(ptStart, _T("\n请输入道路的长度<任意>:"), &nDist); if(ret0 != RTNORM) nDist = 0; } else if(nKeyIndex == 2){ csPrompt.Format(_T("\n请输入道路倒角半径<%.0f>:"), nFilletRad); ads_getdist(ptStart, csPrompt, &nFilletRad); } continue; } else if(ret != RTNORM){ break; } ptEnd = jig.GetPickPoint(); AssureInCurrentView(ptStart, ptEnd); double nAng = ads_angle(ptStart, ptEnd); XPoint ptS1, ptS2, ptE1, ptE2; ads_polar(ptStart, nAng + PI/2, nRoadWidth/2, ptS1); ads_polar(ptStart, nAng - PI/2, nRoadWidth/2, ptS2); ads_polar(ptEnd, nAng + PI/2, nRoadWidth/2, ptE1); ads_polar(ptEnd, nAng - PI/2, nRoadWidth/2, ptE2); { CString csWidth; XPushVarStr clayer(_T("CLAYER"), LAY_TWT_DOTE);//绘制基线 DrawLine(ptStart, ptEnd); entLast.GetLast(); csWidth.Format(_T("%.0f"), nRoadWidth); WriteXdata(entLast, _T("ROADWIDTH"), csWidth); } ////////////////////////////////////////////////////////////////////////// // 以下处理起点 if(!!entBase){ XLine ltmp(entBase, 1); XPoint ptTmp; if(ptStart == ltmp.StartPoint()) ads_polar(ptStart, ltmp.Direction(), nRoadWidth/2, ptTmp); else if(ptStart == ltmp.EndPoint()) ads_polar(ptStart, ltmp.Direction()-PI, nRoadWidth/2, ptTmp); if(!!ptTmp){ //3 起点在另外道路的端点 GetRoad2LineByPt(entBase, ent3, ent4, ptTmp); DrawLine(ptS1, ptE1); ent1.GetLast(); DrawLine(ptS2, ptE2); ent2.GetLast(); if(!!ent3 && !!ent4) FilletNextRoad(ent1, ent2, ent3, ent4, nFilletRad); } else{ //5 起点在另外道路的中间, 生成3通 GetRoad2LineByPt(entBase, ent3, ent4, ptStart); DrawLine(ptS1, ptE1); ent1.GetLast(); DrawLine(ptS2, ptE2); ent2.GetLast(); if(!!ent3 && !!ent4) TrimFillet3Road(ent1, ent2, ent3, ent4, nFilletRad); } } else{ DrawLine(ptS1, ptE1); ent1.GetLast(); DrawLine(ptS2, ptE2); ent2.GetLast(); } if(num == 2){// 7 起点在3通处, 生成4通 Do3ConnectTo4Connect(entLast, ent1, ent2, ptStart, nFilletRad); } ////////////////////////////////////////////////////////////////////////// // 以下处理终点 Entity entEnd; int num2 = GetBaseRoadByPt(ptEnd, entLast, entEnd); if(!!entEnd){ XLine ltmp(entEnd, 1); XPoint ptTmp; if(ptEnd == ltmp.StartPoint()) ads_polar(ptEnd, ltmp.Direction(), nRoadWidth, ptTmp); else if(ptEnd == ltmp.EndPoint()) ads_polar(ptEnd, ltmp.Direction()-PI, nRoadWidth, ptTmp); if(!!ptTmp){ // 4 终点在另外道路的端点 GetRoad2LineByPt(entEnd, ent3, ent4, ptTmp); if(!!ent3 && !!ent4) FilletNextRoad(ent1, ent2, ent3, ent4, nFilletRad); } else{ //6 终点在另外道路的中间, 生成3通 GetRoad2LineByPt(entEnd, ent3, ent4, ptEnd); if(!!ent3 && !!ent4) TrimFillet3Road(ent1, ent2, ent3, ent4, nFilletRad); } } if(num2 == 2){// 7 终点在3通处, 生成4通 Do3ConnectTo4Connect(entLast, ent1, ent2, ptEnd, nFilletRad); } TrimInterRoad(entLast, ent1, ent2, nFilletRad); //2 穿过别的道路, 4通倒圆角 ptStart = ptEnd; entBase = entLast; } regProp.SetValue(_T("FilletRad"), nRoadWidth); regProp.SetValue(_T("RoadWidth"), nFilletRad); SHads_command(RTNONE); }