Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

612 lines
20 KiB
C++

/********************************************************************
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("<or"),
-4, _T("<and"), RTDXF0, _T("ARC"), 8, LAY_TWT_ROAD, -4, _T("and>"),
-4, _T("<and"), RTDXF0, _T("LINE"), 8, LAY_TWT_ROAD, -4, _T("and>"),
-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<len;i++){
XPoint ptTmpInter, ptInt1, ptInt2, ptInt3, ptInt4;
Entity ent = ss[i];
XLine line5(ent, 1);
line5.SetLineFlag(1);
AssureInCurrentView(line5.StartPoint(), line5.EndPoint());
if(!line.Intersection(&line5, ptTmpInter))
continue;
Entity ent3, ent4, ent5, ent6;
GetRoad2LineByPt(ent, ent3, ent4, ptTmpInter);
XLine line3(ent3, 1);
XLine line4(ent4, 1);
line3.SetLineFlag(1);
line4.SetLineFlag(1);
GetRoad2LineByPt(entLast, ent5, ent6, ptTmpInter);
XLine line7(ent5, 1);
XLine line8(ent6, 1);
line7.SetLineFlag(1);
line8.SetLineFlag(1);
line7.Intersection(&line3, ptInt1);
line7.Intersection(&line4, ptInt2);
line8.Intersection(&line3, ptInt3);
line8.Intersection(&line4, ptInt4);
if(!ptInt1 || !ptInt2 || !ptInt3 || !ptInt4)
continue;
// ptInt1 = Wcs2Ucs(ptInt1);
// ptInt2 = Wcs2Ucs(ptInt2);
// ptInt3 = Wcs2Ucs(ptInt3);
// ptInt4 = Wcs2Ucs(ptInt4);
Entity entNew5, entNew6, entNew3, entNew4;
BreakEntity(ent5, Wcs2Ucs(ptInt1), Wcs2Ucs(ptInt2));
entNew5.GetLast();
BreakEntity(ent6, Wcs2Ucs(ptInt3), Wcs2Ucs(ptInt4));
entNew6.GetLast();
BreakEntity(ent3, Wcs2Ucs(ptInt1), Wcs2Ucs(ptInt3));
entNew3.GetLast();
BreakEntity(ent4, Wcs2Ucs(ptInt2), Wcs2Ucs(ptInt4));
entNew4.GetLast();
if(nFilletRad < 0.001) //不倒角了
continue;
//打断之后总共8根线 5,6 是一条道, 3,4是另一条道
XPoint ptL5, ptL5New, ptL6, ptL6New, ptL3, ptL3New, ptL4, ptL4New;
XLine l5(ent5, 1);
if(l5.StartPoint() == ptInt1 || l5.EndPoint() == ptInt1){
ptL5New = ptInt2;
ptL5 = ptInt1;
}
else{
ptL5New = ptInt1;
ptL5 = ptInt2;
}
XLine l6(ent6, 1);
if(l6.StartPoint() == ptInt3 || l6.EndPoint() == ptInt3){
ptL6New = ptInt4;
ptL6 = ptInt3;
}
else{
ptL6New = ptInt3;
ptL6 = ptInt4;
}
XLine l3(ent3, 1);
if(l3.StartPoint() == ptInt1 || l3.EndPoint() == ptInt1){
ptL3New = ptInt3;
ptL3 = ptInt1;
}
else{
ptL3New = ptInt1;
ptL3 = ptInt3;
}
XLine l4(ent4, 1);
if(l4.StartPoint() == ptInt2 || l4.EndPoint() == ptInt2){
ptL4New = ptInt4;
ptL4 = ptInt2;
}
else{
ptL4New = ptInt2;
ptL4 = ptInt4;
}
if(ptL5 == ptL3)
FilletEntity(ent3, ent5, nFilletRad);
else if(ptL5 == ptL3New)
FilletEntity(entNew3, ent5, nFilletRad);
else if(ptL5 == ptL4)
FilletEntity(ent4, ent5, nFilletRad);
else if(ptL5 == ptL4New)
FilletEntity(entNew4, ent5, nFilletRad);
if(ptL6 == ptL3)
FilletEntity(ent3, ent6, nFilletRad);
else if(ptL6 == ptL3New)
FilletEntity(entNew3, ent6, nFilletRad);
else if(ptL6 == ptL4)
FilletEntity(ent4, ent6, nFilletRad);
else if(ptL6 == ptL4New)
FilletEntity(entNew4, ent6, nFilletRad);
if(ptL5New == ptL3)
FilletEntity(ent3, entNew5, nFilletRad);
else if(ptL5New == ptL3New)
FilletEntity(entNew3, entNew5, nFilletRad);
else if(ptL5New == ptL4)
FilletEntity(ent4, entNew5, nFilletRad);
else if(ptL5New == ptL4New)
FilletEntity(entNew4, entNew5, nFilletRad);
if(ptL6New == ptL3)
FilletEntity(ent3, entNew6, nFilletRad);
else if(ptL6New == ptL3New)
FilletEntity(entNew3, entNew6, nFilletRad);
else if(ptL6New == ptL4)
FilletEntity(ent4, entNew6, nFilletRad);
else if(ptL6New == ptL4New)
FilletEntity(entNew4, entNew6, nFilletRad);
}
}
int GetBaseRoadByPt(XPoint pt, Entity ent, Entity &entBase)
{
RBList rbMask(RTDXF0, _T("LINE"), 8, LAY_TWT_DOTE, NULL);
PickSet ss(SS_FREE);
XPoint ptUcs = Wcs2Ucs(pt);
GetPointPickSet(ptUcs, ss, rbMask, 5);
if(!!ent)
ss -= ent;
int len = ss.Length();
if(ss.Length() == 1)
entBase = ss[0L];
return len;
}
void GetRoadByLine(Entity ent, PickSet &ss)
{
XLine lBase(ent, 1);
lBase.SetLineFlag(1);
RBList rbMask(RTDXF0, _T("LINE"), 8, LAY_TWT_ROAD, NULL);
struct resbuf *pointlist;
pointlist = ads_buildlist(RTPOINT, &lBase.StartPoint(), RTPOINT, &lBase.EndPoint(), NULL);
ss.Get(_T("F"), pointlist, NULL, rbMask);
ads_relrb(pointlist);
ss -= ent;
int len = ss.Length();
}
void Do3ConnectTo4Connect(Entity entBase, Entity ent1, Entity ent2, XPoint ptStart, double nFilletRad)
{
XLine lBase(entBase, 1);
XLine lRoad1(ent1, 1);
XLine lRoad2(ent2, 1);
lBase.SetLineFlag(1);
lRoad1.SetLineFlag(1);
lRoad2.SetLineFlag(1);
CString csWidth;
csWidth = ReadXdata(entBase, _T("ROADWIDTH"));
double nWidth = _tstof(csWidth);
PickSet ss1(SS_FREE), ss2(SS_FREE);
GetRoadByLine(ent1, ss1);
if(ss1.Length() != 1)
return;
Entity entIntRoad1 = ss1[0L];
GetRoadByLine(ent2, ss2);
if(ss2.Length() != 1)
return;
Entity entIntRoad2 = ss2[0L];
if(entIntRoad2 == entIntRoad1){ //接直道路, 先TRIM, 然后FILLET
XLine lRoadInt(entIntRoad1, 1);
lRoadInt.SetLineFlag(1);
XPoint ptInt1, ptInt2;
int ret1 = lRoad1.Intersection(&lRoadInt, ptInt1);
int ret2 = lRoad2.Intersection(&lRoadInt, ptInt2);
double nDist1 = ads_distance(ptInt1, ptStart);
double nDist2 = ads_distance(ptInt2, ptStart);
if(nDist1 > 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<int> 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);
}