#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); } }