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

468 lines
12 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 "ArcRadDimStyle.h"
extern AcDbObjectId AddToSpace(Adesk::Boolean bClosed, TDbEntity *pEntSymb) ;
EDimState g_eDimState = eSingleDim;
extern TARCH_IMPEXP BOOL g_bTextDefaultLayer;
namespace
{
#if ADS <= 18
double _ttof(LPCTSTR psz)
{
if (!psz) return .0;
USES_CONVERSION;
return atof(W2A(psz));
}
#endif
}
CArcRadDimStyle::CArcRadDimStyle(void)
{
}
CArcRadDimStyle::~CArcRadDimStyle(void)
{
}
CString GetDimPostfix(AcDbObjectId & dimStyleId)
{
CString strPostfix = _T("");
if (dimStyleId)
{
OPENOBJ_BEGIN(dimStyleId, AcDb::kForRead, AcDbDimStyleTableRecord, pStyle);
if (pStyle != NULL)
{
strPostfix = pStyle->dimpost();
}
OPENOBJ_END();
}
return strPostfix;
}
void CArcRadDimStyle::ArcRadDimensioning()
{
EDimState eDimState = g_eDimState;
int iOsMode = 0;
TGGetVar(_T("OSMODE"), &iOsMode);
iOsMode %= 0x4000; // 在对象捕捉关闭时,打开对象捕捉
iOsMode |= OS_NEA;
XPushVar<int> vOsMode(_T("OSMODE"), iOsMode | OS_NEA);
CRoadCornerRadiusDlg *pDlg = new CRoadCornerRadiusDlg;
while (1)
{
switch (eDimState)
{
case eBatchDim:
{
eDimState = BatchDimensioning(pDlg);
g_eDimState = eBatchDim;
break;
}
case eSingleDim:
{
eDimState = SingleDimensioning(pDlg);
g_eDimState = eSingleDim;
break;
}
case eCancle:
delete pDlg;
return;
}
}
}
EDimState CArcRadDimStyle::BatchDimensioning(CRoadCornerRadiusDlg* dlg)
{
PickSet ss(SS_FREE);
TRBList rbFilter(acutBuildList(RTDXF0, _T("POLYLINE,LWPOLYLINE,ARC"), NULL));
TCHAR chRet;
const TCHAR *kword=_T("Q S");
THookMsg hookmsg;
while (1)
{
acedGetAcadFrame()->SetFocus();
TDPtrList<TGGeCurveSegment> lstSegArc;
int iRetCode = SelectEntities(_T("\n请批量选择待标注的圆弧或[单个标注(Q)/设置(S)]<退出>:"), ss, rbFilter, kword, chRet);//方块
int vn = hookmsg.GetValue();
if (iRetCode == RTNORM)//选择标注
{
CStringList lstLayer;
dlg->GetSelectLayer(lstLayer);
int iIndex(0);
for (long n = 0; n < ss.Length(); ++n)
{
Entity ssEnt=ss[n];
OPENOBJ_BEGIN(ssEnt,AcDb::kForRead,AcDbEntity,pEntity);
if(pEntity)
{
CString strLayer = pEntity->layer();
//add tyj 20160905: 道路半径图层为空时,对所有选中的并且程序支持的对象均进行半径标注
if(lstLayer.IsEmpty())
{
AnalysisTgEntToCircle(pEntity, lstSegArc);
}
else
{
if (!lstLayer.GetSize() || lstLayer.Find(strLayer))
AnalysisTgEntToCircle(pEntity, lstSegArc);
else
iIndex++;
}
}
OPENOBJ_END();
if (iIndex == ss.Length())
acutPrintf(_T("选择对象图层无效,请重新选择!"));
}
for (int i = 0; i < lstSegArc.Length(); ++i)
{
TGGeCurveSegment seg = *lstSegArc[i];
XArc xArc = seg.GetArc();
TADSGePoint3d mid(xArc.MidPoint());
if (dlg->GetRadiusLabel())
DimArcRadDim(dlg, xArc.MidPoint(), xArc);
else
DimArcTextDim(dlg, mid, xArc);
}
}
else if (iRetCode == RTKWORD)
{
switch(chRet)
{
case _T('Q'):
return eSingleDim;
case _T('S'):
{
if (IDOK == dlg->DoModal())
{
}
}
break;
}
}
else
{
//当前焦点在CAD上,并且没有选中
if(vn == 0 && GetFocus() == acedGetAcadDwgView()->GetSafeHwnd())
{
acutPrintf(_T("\n请选择弧线!"));
continue;
}
else
return eCancle;
}
}
}
EDimState CArcRadDimStyle::SingleDimensioning(CRoadCornerRadiusDlg* dlg)
{
AcDbEntity *pEntity=NULL;
Entity ent;
int nRet;//PickSet的返回码
THookMsg hookmsg;
XPoint ptSel;
while (1)
{
TDPtrList<TGGeCurveSegment> lstSegArc;
acedGetAcadFrame()->SetFocus();
TCHAR cRet;
int vn = hookmsg.GetValue();
TRBList rbFilter(acutBuildList(RTDXF0, _T("POLYLINE,LWPOLYLINE,ARC"), NULL));
INITGET_BEG(0, _T("Q S"),)
nRet = SelectEntity1(_T("\n请点取待标注的圆弧或[批量标注(Q)/设置(S)]<退出>:"),ent, ptSel, rbFilter);
INITGET_END();
if (nRet==RTNORM)
{ //单选无限制,屏蔽
//CStringList lstLayer;
//dlg->GetSelectLayer(lstLayer);
OPENOBJ_BEGIN(ent,AcDb::kForRead,AcDbEntity,pEntity);
if(pEntity)
{ //单选无限制,屏蔽
//CString strLayer = pEntity->layer();
//if (!lstLayer.GetSize() || lstLayer.Find(strLayer))
AnalysisTgEntToCircle(pEntity, lstSegArc);
}
OPENOBJ_END();
//tyj 20160825 修改:将下面这句转换坐标放到for循环外面,解决重复转换造成的错误
ptSel = Ucs2Wcs(ptSel);
for (int i = 0; i < lstSegArc.Length(); ++i)
{
TGGeCurveSegment seg = *lstSegArc[i];
XArc xArc = seg.GetArc();
XPoint ptCloseSelPt;
if (dlg->GetRadiusLabel())//半径标注
{
if (xArc.PtOnArc(ptSel))//世界坐标系进行切换
DimArcRadDim(dlg, ptSel, xArc);
}
else//文字标注
{
if (xArc.PtOnArc(ptSel))
DimArcTextDim(dlg, ptSel, xArc);
}
}
}
else if (nRet==RTKWORD)
{
XString sKeyword;
VERIFY(ads_getinput(sKeyword)==RTNORM);
if(sKeyword[0]==_T('Q'))
return eBatchDim;
else if(sKeyword[0] == _T('S'))
{
dlg->DoModal();
}
}
else
{
//当前焦点在CAD上,并且没有选中
/* if(vn == 0 && GetFocus() == acedGetAcadDwgView()->GetSafeHwnd())
{
acutPrintf(_T("\n请选择弧线!"));
continue;
}
else */
return eCancle;
}
}
}
void CArcRadDimStyle::AnalysisTgEntToCircle(const AcDbEntity* pEnt, TDPtrList<TGGeCurveSegment> &lstResult)
{
if(pEnt->isKindOf(AcDbArc::desc()))
{
AcDbArc *pArc = AcDbArc::cast(pEnt);
TADSGePoint3d ptCen;
(AcGePoint3d &)ptCen = pArc->center();
TGGeArc ar(ptCen, pArc->radius(), pArc->startAngle(), pArc->endAngle());
TADSGePoint3d ptStart, ptEnd, ptMid;
ar.GetStartPoint(ptStart);
ar.GetEndPoint(ptEnd);
ar.MidPoint(ptMid);
TGGeCurveSegment *pSeg = new TGGeCurveSegment;
*pSeg = TGGeArc(ptStart, ptMid, ptEnd);
lstResult.Append(pSeg);
}
else if (pEnt->isKindOf(AcDbPolyline::desc()) || pEnt->isKindOf(AcDb2dPolyline::desc()))//add tyj 20160909:二维多段线也可以进行半径标注
{
AcDbPolyline pline;
TEntitySet ent;
if(acdbGetAdsName(ent.name, pEnt->objectId()) == Acad::eOk)
{
TGGePoly2D poly(ent);
for (int i = 0; i < poly.TotalSegments(); i++)
{
TGGeCurveSegment *pSeg = new TGGeCurveSegment;
poly.Nth(i, *pSeg);
if (abs(pSeg->GetBulge()) > 1.0e-6)
lstResult.Append(pSeg);
else
delete pSeg;
}
}
}
}
void CArcRadDimStyle::DimArcRadDim(CRoadCornerRadiusDlg* dlg, const XPoint &ptOnArc, XArc &xArc)
{
XPoint ptCenter;
AcGePoint3d ptText;
CString strPostfix;
int nDimLength;
ptCenter = xArc.GetCenterPt();
double dRad = xArc.GetRadius();
CString strPrefix,strDimText;
if (dlg->GetEqu())
{
strPrefix = _T("R=");
nDimLength = 20;
}
else
{
strPrefix = _T("R");
nDimLength = 17;
}
AcDbObjectId dimStyleId = dlg->InitLabelStyle(dlg->GetDrawUnit());
strPostfix = GetDimPostfix(dimStyleId);
switch(dlg->GetAccuracy())
{
case 0:
{
strDimText.Format(_T("%s%.0f%s"), strPrefix, _AS_METER(dRad), strPostfix);
break;
}
case 1:
{
strDimText.Format(_T("%s%.1f%s"), strPrefix, _AS_METER(dRad), strPostfix);
break;
}
case 2:
{
strDimText.Format(_T("%s%.2f%s"), strPrefix, _AS_METER(dRad), strPostfix);
break;
}
case 3:
{
strDimText.Format(_T("%s%.3f%s"), strPrefix, _AS_METER(dRad), strPostfix);
break;
}
}
TDbRadiusDim *pDim=new TDbRadiusDim;
// jsx add 160914,增加布局转角的设置,解决UCS下,文字方向错误的问题
pDim->SetLayoutRotation(Ucs2Wcs(0.0));
pDim->SetStyleId(dimStyleId);
pDim->SetDimCenter(xArc.GetCenterPt());
pDim->SetDimEndPoint(ptOnArc);
pDim->SetDimLen(nDimLength);
if (dlg->GetEqu())
{
pDim->SetText(strDimText);
}
double nDimDist=pDim->GetDimLen(FALSE);
//del tyj 20160909:需求变更,无论圆弧半径多大,道路半径标注始终默认在圆弧内侧标注。
//if(nDimDist>xArc.GetCenterPt().Distance2d(ptOnArc))
// pDim->SetDimLen(-nDimDist, FALSE);
pDim->SetDiameter(FALSE);
pDim->setLayer(InitLayer(LAY_DIM));
// AcGeVector3d vec = ptCenter - ptOnArc;//向量
// XPoint ptPos = pDim->GetTextPos(); //获取文字位置
// ptPos = ptPos + (DocGetPScale() * 2)* vec / vec.length();
// pDim->SetTextPos(ptPos); //调整文字位置
AddToSpace(Adesk::kTrue, (TDbEntity*)pDim);
SHacedCommand(RTSTR, _T("REGEN"), RTNONE);
}
void CArcRadDimStyle::DimArcTextDim(CRoadCornerRadiusDlg* dlg, XPoint &ptOnArc, XArc &xArc)//ptOnArc是世界坐标系的点
{
XPoint ptCenter;
AcGePoint3d ptText;
ptCenter = xArc.GetCenterPt();
double dir = xArc.GetRadius()/2;
double angle = 0.0;
XPoint ptLocation = ptOnArc;
TDbText *pText = new TDbText;
CString strPrefix, sValue, strPostfix;
AcDbObjectId dimStyleId = dlg->InitLabelStyle(dlg->GetDrawUnit());
strPostfix = GetDimPostfix(dimStyleId);
if (dlg->GetEqu())
{
strPrefix = _T("R=");
}
else
{
strPrefix = _T("R");
}
switch(dlg->GetAccuracy())
{
case 0:
sValue.Format(_T("%s%.0f%s"), strPrefix, _AS_METER(xArc.GetRadius()), strPostfix);
break;
case 1:
sValue.Format(_T("%s%.1f%s"), strPrefix, _AS_METER(xArc.GetRadius()), strPostfix);
break;
case 2:
sValue.Format(_T("%s%.2f%s"), strPrefix, _AS_METER(xArc.GetRadius()), strPostfix);
break;
case 3:
sValue.Format(_T("%s%.3f%s"), strPrefix, _AS_METER(xArc.GetRadius()), strPostfix);
break;
}
XPoint ptMin, ptMax;
pText->SetText(sValue);
pText->SetHeight(_ttof(dlg->GetTextHeigh()));
AcDbObjectId idTextStyle = GetTextStyleId(dlg->GetTextStyle());
if (idTextStyle.isValid())
pText->SetStyleId(idTextStyle);
else
pText->SetStyleId(acdbCurDwg()->textstyle());
pText->setLayer(InitLayer(LAY_TEXT));//公文图层
//计算文字插入位置和旋转方向
if (dlg->GetTextDir())//文字方向为沿切线
{
//在1:500,字高3.5的时候,文字中心距离圆弧线2000;在1:100,字高3.5的时候,文字中心距离圆弧线400;在1:500,字高5.0的时候,文字中心距离圆弧线2857,以此类推
double dDisPtLoc2Arc = (DocGetPScale() / 500.0 * _ttof(dlg->GetTextHeigh()) / 3.5) * 2000;//(字高/3.5 * 比例/500)*2000
AcGeVector3d vec = ptCenter - ptOnArc;
ptLocation = ptOnArc + vec * dDisPtLoc2Arc / vec.length();
pText->SetAlignment(XExplodeDraw::kMiddleCenter);
pText->SetLocation(ptLocation);
angle = ads_angle(XPoint(ptCenter), XPoint(ptOnArc));
//用户坐标系下进行文字的翻转
ptOnArc = Wcs2Ucs(ptOnArc);
ptCenter = Wcs2Ucs(ptCenter);
if (ptOnArc.y < ptCenter.y)
angle += 0.5 * PI;
else
angle -= 0.5 * PI;
pText->SetRotation(angle);
}
else//文字方向沿Y轴
{
//add tyj 20160824:计算在用户坐标系下,文字的方向角度
AcGeVector3d vtYAxisUCS = Ucs2Wcs(AcGeVector3d::kYAxis, true);
// Ucs的Y轴在Wcs下X轴方向的角度
double dRot = acutAngle(asDblArray(AcGePoint3d::kOrigin), asDblArray(vtYAxisUCS));
angle = dRot - 0.5*PI;
XPoint ptAng = pText->GetExtents();//获取到的点的X是文字的宽度,Y为文字的高度
XPoint ptss(0, 0, 0);
ptAng = Ucs2Wcs(ptAng);
ptAng = (ptAng.x / 2, ptAng.y / 2);
AcGeVector3d vec = ptCenter - ptOnArc;//向量
AcGeVector3d vecs = ptss - ptAng;//
double angles = vec.angleTo(vecs);//向量与向量夹角
double dMins = angles;
XPoint ptTemp = (ptAng.x, -ptAng.y);
vecs = ptss - ptTemp;//
angles = vec.angleTo(vecs);
dMins < angles ? dMins : dMins = angles;
ptTemp = (-ptAng.x, -ptAng.y);
vecs = ptss - ptTemp;//
angles = vec.angleTo(vecs);
dMins < angles ? dMins : dMins = angles;
ptTemp = (-ptAng.x, ptAng.y);
vecs = ptss - ptTemp;//
angles = vec.angleTo(vecs);
dMins < angles ? dMins : dMins = angles;
angles = dMins;
//pText->GetExtents2d(ptMin, ptMax);//获取包围盒,必须在最后,要不什么也获取不到,获取值为相对文字中心点的
//double dXWidth = (ptMax.x - ptMin.x),
// dYHeigh = (ptMax.y - ptMin.y);//计算大小
//在1:500时,无论字高多少,文字外包围框离圆弧线最近点的距离为1000;在1:100时,无论字高多少,文字外包围框离圆弧线最近点的距离为200,以此类推。
double dDisPtLoc2Arc = DocGetPScale() / 500.0 * 1000;
vec = ptCenter - ptOnArc;
ptLocation = ptOnArc + vec * dDisPtLoc2Arc / vec.length();
ptOnArc = Wcs2Ucs(ptOnArc);
ptCenter = Wcs2Ucs(ptCenter);
AcGeVector3d vecQuadrant = ptOnArc - ptCenter;
if (vecQuadrant.x <= 0 && vecQuadrant.y >= 0)
pText->SetAlignment(XExplodeDraw::kTopLeft);
else if (vecQuadrant.x >= 0 && vecQuadrant.y >= 0)
pText->SetAlignment(XExplodeDraw::kTopRight);
else if (vecQuadrant.x <= 0 && vecQuadrant.y <= 0)
pText->SetAlignment(XExplodeDraw::kBottomLeft);
else if (vecQuadrant.x >= 0 && vecQuadrant.y <= 0)
pText->SetAlignment(XExplodeDraw::kBottomRight);
else
pText->SetAlignment(XExplodeDraw::kCenter);
pText->SetRotation(angle);
pText->SetLocation(ptLocation);
}
AddToModelSpace(pText, Adesk::kTrue);
}