Files
envi-code/SourceCode/Code2026/tg_shs/shs_siteplan/commonRoad.cpp
T

620 lines
16 KiB
C++
Raw Normal View History

2026-09-28 15:28:50 +08:00
#include "StdAfx.h"
#include "commonRoad.h"
namespace TRoadCommon
{
// 点相对于线段的关系,左侧,右侧,线段(所在的直线)上,
// dTol:判断点是否在线上
EPointToLine PointToLineSegPerp(const AcGeLineSeg2d &lineseg, const AcGePoint2d &point, double dTol)
{
if (ToLine(lineseg).distanceTo(point) < dTol)
return eOnLine;
// 叉积:
AcGeVector2d vecLine = lineseg.direction();
AcGeVector2d vecAccurate = point - lineseg.startPoint();
return vecLine.x * vecAccurate.y - vecLine.y * vecAccurate.x > 0 ? eLeft : eRight;
}
// 根据圆弧的clockwise,以及相对的半径来判断
EPointToLine PointToArcPerp(const AcGeCircArc2d &arc, const AcGePoint2d &point, double dTol)
{
double dRaidus = arc.radius();
double dDisAccurate = point.distanceTo(arc.center());
// 注意:如果圆弧半径过小,会发生问题。
if (fabs(dRaidus - dDisAccurate) < dTol)
return eOnLine;
else
{
if (arc.isClockWise())
{
return dDisAccurate < dRaidus ? eRight : eLeft;
}
else
{
return dDisAccurate < dRaidus ? eLeft : eRight;
}
}
}
EPointToLine PointToLineSegDir(const AcGeLineSeg2d &lineseg, const AcGePoint2d &point, double dTol)
{
AcGeVector2d vecLine = lineseg.direction();
AcGeVector2d vecPerp = vecLine.perpVector();
AcGeLineSeg2d startLine(lineseg.startPoint(), lineseg.startPoint() + vecPerp);
AcGeLineSeg2d endLine(lineseg.endPoint(), lineseg.endPoint() + vecPerp);
EPointToLine es = PointToLineSegPerp(startLine, point, dTol);
EPointToLine ee = PointToLineSegPerp(endLine, point, dTol);
if (es == eOnLine && ee == eOnLine)
return eOnLine; // 点和两端都接近的情况
else if (es == eLeft)
return eStartOut;
else if (es == eOnLine)
return eStartPoint;
else if (ee == eRight)
return eEndOut;
else if (ee == eOnLine)
return eEndPoint;
else
return eOnLine;
}
EPointToLine PointToArcDir(const AcGeCircArc2d &arcIn, const AcGePoint2d &point, double dTol)
{
ASSERT(dTol > 0);
// get Attirbute
AcGePoint2d startPoint = arcIn.startPoint();
AcGePoint2d endPoint = arcIn.endPoint();
AcGePoint2d centerPoint = arcIn.center();
bool bClock = arcIn.isClockWise() ? true : false;
double dRadius = arcIn.radius();
// 计算圆弧上的各个角度
double dangleStart = AcGeVector2d(startPoint-centerPoint).angle();
double dangleEnd = AcGeVector2d(endPoint - centerPoint).angle();
double dangleAccurate = AcGeVector2d(point - centerPoint).angle();
double dAntiMidAngle = AddAngleInClock(bClock, dangleStart, AngleInClock(bClock, dangleStart, dangleEnd)*0.5); // 首先获取midAngle
dAntiMidAngle = AntiAngle(dAntiMidAngle); // 获取antiMidAngle
// 计算相对于antiAngle的夹角
dangleStart = AngleInClock(bClock, dAntiMidAngle, dangleStart);
dangleEnd = AngleInClock(bClock, dAntiMidAngle, dangleEnd);
dangleAccurate = AngleInClock(bClock, dAntiMidAngle, dangleAccurate);
// 这类的角度都是相对于dAntiStart的角度,
double dStartlen = dangleStart * dRadius;
double dEndLen = dangleEnd * dRadius;
double dAccurateLen = dangleAccurate * dRadius;
if (fabs(dStartlen - dAccurateLen) < dTol && fabs(dEndLen - dAccurateLen) < dTol )
return eOnLine;
else if (fabs(dStartlen - dAccurateLen) < dTol)
return eStartPoint;
else if (dAccurateLen < dStartlen)
return eStartOut;
else if (fabs(dEndLen - dAccurateLen) < dTol)
return eEndPoint;
else if (dEndLen < dAccurateLen)
return eEndOut;
else
return eOnLine;
}
AcGeCircArc2d OutSideArc(const AcGeCircArc2d &arcTem, double dHalfWid)
{
return ConNewArc(arcTem, arcTem.radius() + dHalfWid);// 半径扩展
}
AcGeCircArc2d InSideArc(const AcGeCircArc2d &arcTem, double dHalfWid)
{
if (arcTem.radius() - dHalfWid < 1.0)
return arcTem;
return ConNewArc(arcTem, arcTem.radius() - dHalfWid);
}
AcDbArc& GeArcToDbSys(const AcGeCircArc2d &arc, AcDbArc &dbArc)
{
AcGePoint2d ptCenter = arc.center();
AcGeVector2d vecStart = arc.startPoint() - ptCenter;
AcGeVector2d vecEnd = arc.endPoint() - ptCenter;
AcGeVector3d norm(0.0, 0.0, 1.0);
dbArc.setCenter(POINT_2D_TO_3D(AsSysUnitPoint2d(ptCenter)));
dbArc.setRadius(_AS_SYS_UNIT(arc.radius()));
dbArc.setNormal(norm);
if (arc.isClockWise())
{
dbArc.setStartAngle(vecEnd.angle());
dbArc.setEndAngle(vecStart.angle());
}
else
{
dbArc.setStartAngle(vecStart.angle());
dbArc.setEndAngle(vecEnd.angle());
}
return dbArc;
}
AcDbArc* GeArcToDbSys(const AcGeCircArc2d &arc)
{
AcDbArc *pArc = new AcDbArc;
GeArcToDbSys(arc, *pArc);
return pArc;
}
AcDbLine* GeLineToDbLineSys(const AcGeLineSeg2d &lineSeg)
{
AcGePoint2d ptStart = lineSeg.startPoint();
AcGePoint2d ptEnd = lineSeg.endPoint();
ptStart = AsSysUnitPoint2d(ptStart);
ptEnd = AsSysUnitPoint2d(ptEnd);
return new AcDbLine(POINT_2D_TO_3D(ptStart), POINT_2D_TO_3D(ptEnd));
}
AcGeLineSeg2d DbLineToGeLineMM(const AcDbLine &dbLine)
{
AcGePoint3d ptStart = dbLine.startPoint();
AcGePoint3d ptEnd = dbLine.endPoint();
ptStart = AsMMUnitPoint3d(ptStart);
ptEnd = AsMMUnitPoint3d(ptEnd);
return AcGeLineSeg2d(POINT_3D_TO_2D(ptStart), POINT_3D_TO_2D(ptEnd));
}
// 首先:AcDbArc据说都是逆时针的
// 还是使用圆心,半径,角度构造圆弧比较靠谱
AcGeCircArc2d DbArcToGeMM(const AcDbArc &dbArc)
{
AcGePoint3d ptCenter3d = dbArc.center();
double dRadius = dbArc.radius();
double dangleStart = dbArc.startAngle();
double dangleEnd = dbArc.endAngle();
return AcGeCircArc2d(POINT_3D_TO_2D(AsMMUnitPoint3d(ptCenter3d)), _AS_MM(dRadius), dangleStart, dangleEnd);
}
void SetLayer(AcDbEntity *pEnt, EEntType entType)
{
if (entType == eRoadEdgeType)
{
if (pEnt->setLayer(InitLayer(LAY_ROAD)) != Acad::eOk)
ads_printf(_T("道路图层设置失败!"));
}
else
{
if (pEnt->setLayer(InitLayer(LAY_ROADDOTE)) != Acad::eOk)
ads_printf(_T("中线图层设置失败!"));
if (g_bMeterUnitDraw)
pEnt->setLinetypeScale(0.001);
}
}
AcGeLineSeg2d LeftLine(const AcGeLineSeg2d &lineseg, double dDis)
{
AcGeVector2d vecPrep = lineseg.direction().perpVector().normalize();
return AcGeLineSeg2d(lineseg.startPoint() + vecPrep * dDis,
lineseg.endPoint() + vecPrep * dDis);
}
AcGeLineSeg2d RightLine(const AcGeLineSeg2d &lineseg, double dDis)
{
AcGeVector2d vecPrep = lineseg.direction().perpVector().normalize();
return AcGeLineSeg2d(lineseg.startPoint() - vecPrep * dDis,
lineseg.endPoint() - vecPrep * dDis);
}
AcGeCircArc2d LeftArc(const AcGeCircArc2d &arc, double dDis)
{
if (arc.isClockWise())
{
return OutSideArc(arc, dDis);
}
else
{
return InSideArc(arc, dDis);
}
}
AcGeCircArc2d RightArc(const AcGeCircArc2d &arc, double dDis)
{
if (!arc.isClockWise())
{
return OutSideArc(arc, dDis);
}
else
{
return InSideArc(arc, dDis);
}
}
// 修改圆弧,而不改变圆心
AcGeCircArc2d ConNewArc(const AcGeCircArc2d &arcTemplate, const AcGePoint2d &ptStart, const AcGePoint2d &ptEnd)
{
AcGePoint2d ptCenter = arcTemplate.center();
AcGeVector2d vecStart = ptStart - ptCenter;
AcGeVector2d vecEnd = ptEnd - ptCenter;
double dStartAngle = vecStart.angle();
double dEndAngle = vecEnd.angle();
if (arcTemplate.isClockWise())
{
dStartAngle = 2 * PI - dStartAngle;
dEndAngle = 2 * PI - dEndAngle;
}
AcGeCircArc2d arc = AcGeCircArc2d(ptCenter,
arcTemplate.radius(),
dStartAngle,
dEndAngle,
AcGeVector2d::kXAxis,
arcTemplate.isClockWise());
return arc;
}
AcGeCircArc2d ConNewArc(const AcGeCircArc2d &arcTemplate, double dRadius)
{
AcGeCircArc2d arc = arcTemplate;
return arc.setRadius(dRadius);
}
AcGeVector2d TanVecOfArcStartPoint(const AcGeCircArc2d &arc)
{
AcGePoint2d ptStart = arc.startPoint();
AcGePoint2d ptCenter = arc.center();
AcGeVector2d vecTan = ptStart - ptCenter;
if (arc.isClockWise())
vecTan.rotateBy(-PI*0.5);
else
vecTan.rotateBy(PI*0.5);
return vecTan.normalize();
}
AcGeVector2d TanVecOfArcEndPoint(const AcGeCircArc2d &arc)
{
AcGePoint2d ptEnd = arc.endPoint();
AcGePoint2d ptCenter = arc.center();
AcGeVector2d vecTan = ptEnd - ptCenter;
if (!arc.isClockWise())
vecTan.rotateBy(-PI*0.5);
else
vecTan.rotateBy(PI*0.5);
return vecTan.normalize();
}
double NormalAngle(double dAngle)
{
return AngleRangeTo2PI(dAngle);
}
double VecAngle(const AcGeVector2d &vec1, const AcGeVector2d &vec2, bool bClock)
{
double dAngle1 = vec1.angle();
double dAngle2 = vec2.angle();
if (bClock)
{ //
return NormalAngle(dAngle1 - dAngle2);
}
else
{
return NormalAngle(dAngle2 - dAngle1);
}
}
// 按照bClockwise的方向,返回angle1和angle2的夹角
double AngleInClock(bool bClockwise, double angle1, double angle2)
{
if (angle2 < angle1)
angle2 += PI*2.0;
// 逆时针的夹角,顺时针的夹角是他跟2PI的差
double dAngleAnti = angle2 - angle1;
if (bClockwise)
{
return PI*2.0 - dAngleAnti;
}
else
{
return dAngleAnti;
}
}
// 向量vec的方向上,对pt1和pt2排序
// ret:-1:pt1 < pt2; 0: pt == pt2;1: pt1 > pt2。
int PointSequence(const AcGeVector2d &vec, const AcGePoint2d &pt1, const AcGePoint2d &pt2, double dTol)
{
double d1 = pt1.asVector().dotProduct(vec);
double d2 = pt2.asVector().dotProduct(vec);
if (fabs(d1 - d2) < dTol)
return 0;
else if (d1 < d2) return -1;
else
return 1;
}
// 圆弧arc的方向上(顺时针,逆时针)对pt1和pt2进行排序.
// 备注:排序的起点是arc另一侧圆弧的中点,方向是按照圆弧的时针方向
// ret:-1:pt1 < pt2; 0: pt == pt2;1: pt1 > pt2。
int PointSequence(const AcGeCircArc2d &arcDir, const AcGePoint2d &pt1, const AcGePoint2d &pt2, double dTol)
{
// 这个函数需要测试一下
AcGePoint2d ptStart = arcDir.startPoint();
AcGePoint2d ptEnd = arcDir.endPoint();
AcGePoint2d ptCenter = arcDir.center();
bool bClock = arcDir.isClockWise() == Adesk::kTrue;
double dStartAngle = AcGeVector2d(ptStart - ptCenter).angle();
double dEndAngle = AcGeVector2d(ptEnd - ptCenter).angle();
double dArcAngle = AngleInClock(bClock, dStartAngle, dEndAngle);
// 计算每个点与这个角度的夹角
double dAccurateStartAngle = AntiAngle(AddAngleInClock(bClock, dStartAngle, dArcAngle*0.5));
AcGeVector2d vecDump1 = pt1 - ptCenter;
AcGeVector2d vecDump2 = pt2 - ptCenter;
double dAngle1 = vecDump1.angle();
double dAngle2 = vecDump2.angle();
double d1, d2;
if (SameAngle(dAccurateStartAngle, dAngle1, dTol))
d1 = 0.0;
else
d1 = AngleInClock(bClock, dAccurateStartAngle, vecDump1.angle());
if (SameAngle(dAccurateStartAngle, dAngle2, dTol))
d2 = 0.0;
else
d2 = AngleInClock(bClock, dAccurateStartAngle, vecDump2.angle());
if (fabs(d1 - d2) < dTol)
return 0;
else if (d1 < d2)
return -1;
else
return 1;
}
AcGePoint2d MidPointOfArc(const AcGeCircArc2d &arc)
{
AcGePoint2d ptStart = arc.startPoint();
AcGePoint2d ptEnd = arc.endPoint();
AcGePoint2d ptCenter = arc.center();
double dRadius = arc.radius();
double dangleStart = AcGeVector2d(ptStart - ptCenter).angle();
double dangleEnd = AcGeVector2d(ptEnd - ptCenter).angle();
double dangleWhole = AngleInClock(arc.isClockWise() ? true : false, dangleStart, dangleEnd);
double dangleMid = AddAngleInClock(arc.isClockWise() ? true : false, dangleStart, dangleWhole * 0.5);
return ptCenter + AcGeVector2d(cos(dangleMid)*dRadius, sin(dangleMid)*dRadius);
}
// 向一端延长直线段
AcGeLineSeg2d ExtendLine(const AcGeLineSeg2d &lineseg, bool bStart, double dExtend)
{
AcGeVector2d lineVec = lineseg.direction();
lineVec.normalize();
if (bStart)
return AcGeLineSeg2d(lineseg.startPoint() - lineVec*dExtend, lineseg.endPoint());
else
return AcGeLineSeg2d(lineseg.startPoint(), lineseg.endPoint() + lineVec*dExtend);
}
// 向一端延长弧线,
AcGeCircArc2d ExtendArc(const AcGeCircArc2d &arc, bool bStart, double dExtendLen)
{
if (bStart)
return ExtendArc(arc, dExtendLen, 0.0);
else
return ExtendArc(arc, 0.0, dExtendLen);
}
AcGeLineSeg2d ExtendLine(const AcGeLineSeg2d &lineseg, double dExtendStart, double dExtendEnd)
{
AcGeLineSeg2d line = ExtendLine(lineseg, true, dExtendStart);
return ExtendLine(line, false, dExtendEnd);
}
AcGeCircArc2d ExtendArc(const AcGeCircArc2d &arc, double dExtendStart, double dExtendEnd)
{
double dRaidus = arc.radius();
if (dRaidus < 1.0)
return arc;
AcGePoint2d ptCenter = arc.center();
AcGePoint2d ptStart = arc.startPoint();
AcGePoint2d ptEnd = arc.endPoint();
bool bClock = arc.isClockWise() == Adesk::kTrue ? true : false;
double dStartAngle = AcGeVector2d(ptStart - ptCenter).angle();
double dEndAngle = AcGeVector2d(ptEnd - ptCenter).angle();
double dArcAngle = AngleInClock(bClock, dStartAngle, dEndAngle);
double dMaxExtendAngle = PI - dArcAngle*0.5; // 最大延伸弧度
double dExtendStartAngle = dExtendStart/dRaidus;
double dExtendEndAngle = dExtendEnd / dRaidus;
bool bOverStart = (dExtendStartAngle - dMaxExtendAngle > 1e-6); // 起始延伸和终止延伸是否越界
bool bOverEnd = (dExtendEndAngle - dMaxExtendAngle > 1e-6);
if (bOverEnd && bOverStart) return AcGeCircArc2d(ptCenter, dRaidus); // 直接返回整个圆
else if (bOverEnd)
{
dExtendEndAngle = dMaxExtendAngle;
}
else if (bOverStart)
{
dExtendStartAngle = dMaxExtendAngle;
}
double dangleStartNew = AddAngleInClock(bClock, dStartAngle, -dExtendStartAngle);
double dangleEndNew = AddAngleInClock(bClock, dEndAngle, dExtendEndAngle);
AcGePoint2d ptStartNew = ptCenter + AcGeVector2d(cos(dangleStartNew)*dRaidus, sin(dangleStartNew)*dRaidus);
AcGePoint2d ptEndNew = ptCenter + AcGeVector2d(cos(dangleEndNew)*dRaidus, sin(dangleEndNew)*dRaidus);
return ConNewArc(arc, ptStartNew, ptEndNew);
}
void ResetLine(AcGeLineSeg2d &line, bool bStart, const AcGePoint2d &ptAccurate)
{
line.set(bStart ? ptAccurate : line.startPoint(), bStart ? line.endPoint() : ptAccurate);
}
void ResetArc(AcGeCircArc2d &arc, bool bStart, const AcGePoint2d &ptAccurate)
{
arc = ConNewArc(arc, bStart ? ptAccurate : arc.startPoint(), bStart ? arc.endPoint() : ptAccurate);
}
double LenOfArc(const AcGeCircArc2d &arc)
{
return arc.length(arc.startAng(), arc.endAng());
}
BOOL SameAngle(double dAngle1, double dAngle2, double dAngleTol)
{
dAngle1 = NormalAngle(dAngle1);
dAngle2 = NormalAngle(dAngle2);
// 判断是否和0度相等,或者和2PI相等。
return (DoubleEqual(fabs(dAngle1 - dAngle2), 0.0, dAngleTol) ||
DoubleEqual(fabs(dAngle1 - dAngle2), PI*2.0, dAngleTol));
}
class CSelectStruct
{
public:
#if ADS > 22
static bool KeyFilter(MSG* msg);
#else
static BOOL KeyFilter(MSG* msg);
#endif
static int SelectEnts(CString csPrompt,PickSet &ssResult, TRBList &rbBaseMask,const TCHAR* szKeyword, TCHAR &chRet);
private:
static CString m_sKeyWordList;
static int m_rtRet;
static TCHAR m_chRet;
};
CString CSelectStruct::m_sKeyWordList;
int CSelectStruct::m_rtRet;
TCHAR CSelectStruct::m_chRet;
////////////////////////////////////////////////////////////////////////////
#if ADS > 22
bool CSelectStruct::KeyFilter(MSG* msg)
#else
BOOL CSelectStruct::KeyFilter(MSG* msg)
#endif
{
if(!acdbCurDwg())
return FALSE;
BOOL bRet = FALSE;
m_sKeyWordList.MakeUpper();
switch(msg->message)
{
case WM_KEYDOWN: //键盘输入关键字
{
if (msg->wParam == VK_RETURN || msg->wParam == VK_SPACE)// 键盘输入回车,键盘输入空格
{
m_rtRet = RTNONE;
msg->wParam = VK_SPACE;
}
else
{
CString sKey(TCHAR(msg->wParam));
sKey.MakeUpper();
if (m_sKeyWordList.Find(sKey) != -1)
{
// ads_printf(sKey);
m_chRet = sKey[0];
m_rtRet = RTKWORD;
msg->wParam = VK_SPACE;
}
}
}
break;
case WM_RBUTTONDOWN: // 鼠标右键
{
m_rtRet = RTNONE;
msg->wParam = VK_SPACE;
}
break;
default:
break;
}
return bRet;
}
int CSelectStruct::SelectEnts(CString csPrompt,PickSet &ssResult, TRBList &rbBaseMask,const TCHAR* szKeyword, TCHAR &chRet)
{
if (szKeyword == NULL)
m_sKeyWordList = _T("");
else
m_sKeyWordList = szKeyword;
m_rtRet = RTERROR;
// 钩子函数监视键盘中输入关键字
acedRegisterFilterWinMsg(KeyFilter);
// 保存返回结果
int nRet = 0;
const TCHAR *szTempPrompts[2]={csPrompt, _T("") };
int iRet = ssResult.Get(_T(":S:$"), szTempPrompts, NULL, rbBaseMask);
if (m_rtRet == RTKWORD)
{
chRet = m_chRet;
nRet = RTKWORD;
}
else if (m_rtRet == RTNONE)
{
nRet = RTNONE;
}
else
nRet = iRet;
// 释放函数
acedRemoveFilterWinMsg(KeyFilter);
return nRet;
}
int SelectEntitiesOnce(CString csPrompt,PickSet &ssResult, TRBList &rbBaseMask,const TCHAR* szKeyword, TCHAR &chRet)
{
return CSelectStruct::SelectEnts(csPrompt, ssResult, rbBaseMask, szKeyword, chRet);
}
}