Files
envi-code/SourceCode/Code2026/tg_shs/shs_annotate/ArcRadDimStyle.cpp
T

467 lines
12 KiB
C++
Raw Normal View History

2026-09-28 15:28:50 +08:00
#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);
}