468 lines
12 KiB
C++
468 lines
12 KiB
C++
#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);
|
||
}
|