Files
envi-code/SourceCode/Code2026/tg_shs/shs_siteplan/commonRoad.cpp
T
2026-09-28 15:28:50 +08:00

621 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}
}