一些概念
-
尺寸标注倾斜度
相对于水平X轴而言
-
尺寸标注样式字段
40 DIMSCALE 设置应用于标注变量(可指定大小、距离或偏移量)的全局比例因子
41 DIMASZ 控制尺寸线、引线箭头的大小
42 DIMEXO 指定尺寸界线偏离原点的距离
44 DIMEXE 指定尺寸线超出尺寸界线的距离
140 DIMTXT 指定标注文字的高度(除非当前文字样式具有固定的高度) -
箭头
箭头大小为长度,高度则为0.2*箭头大小,若放不下,增加的引线长也为箭头长度即可。 -
文字倾斜角度
在文字样式中增加了倾斜角度 -
尺寸标注箭头太大时,autocad的处理方式
-
标注样式替代
代码实现
代码只是用来演示绘制思路,依赖其他一些代码,故不可直接运行。
- 总体思路
//标注点
auto pDimPointGeom = DrawDimPoints();
if (pDimPointGeom) pRtOsgGeode->addDrawable(pDimPointGeom);
//绘制尺寸标注线
auto pDimLineGeom = DrawDimLine();
if (pDimLineGeom) pRtOsgGeode->addDrawable(pDimLineGeom);
//绘制两根尺寸界线
auto pDimBorderLineGeom = DrawDimBorderLine();
if (pDimBorderLineGeom) pRtOsgGeode->addDrawable(pDimBorderLineGeom);
//绘制箭头
auto pArrowGeom = DrawArrow();
if (pArrowGeom) pRtOsgGeode->addDrawable(pArrowGeom);
//绘制文字
DrawDimText(nModelFlag, pRtOsgGeode);
- 部分代码
osg::ref_ptr<osg::Drawable> DrawerGMAlignedDimension::DrawDimPoints()
{
osg::Geometry* pDimPointGeom = new osg::Geometry();
osg::Vec3dArray* pVertexArray = new osg::Vec3dArray();
pVertexArray->push_back(osg::Vec3d(m_ptDimPoint1.x,
m_ptDimPoint1.y, m_ptDimPoint1.z));
pVertexArray->push_back(osg::Vec3d(m_ptDimPoint2.x,
m_ptDimPoint2.y, m_ptDimPoint2.z));
pDimPointGeom->setVertexArray(pVertexArray);
pDimPointGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,
0, pVertexArray->size()));
return pDimPointGeom;
}
osg::ref_ptr<osg::Drawable> DrawerGMAlignedDimension::DrawDimLine()
{
AcGeVector3d vDimPtToDimLineOffset = m_ptDimLinePoint - m_ptDimPoint2;//标注点到标注线的偏移向量
AcGePoint3d ptDimLineStart = m_ptDimPoint1 + vDimPtToDimLineOffset;//标注线起点
AcGePoint3d ptDimLineEnd = m_ptDimPoint2 + vDimPtToDimLineOffset;//标注线末点
osg::Geometry* pDimLineGeom = new osg::Geometry();
osg::Vec3dArray* pVertexArray = new osg::Vec3dArray();
pVertexArray->push_back(osg::Vec3d(ptDimLineStart.x,
ptDimLineStart.y, ptDimLineStart.z));
pVertexArray->push_back(osg::Vec3d(ptDimLineEnd.x,
ptDimLineEnd.y, ptDimLineEnd.z));
pDimLineGeom->setVertexArray(pVertexArray);
pDimLineGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,
0, pVertexArray->size()));
return pDimLineGeom;
}
osg::ref_ptr<osg::Drawable> DrawerGMAlignedDimension::DrawDimBorderLine()
{
//标注点到标注线的偏移向量
AcGeVector3d vDimPtToDimLineOffset = m_ptDimLinePoint - m_ptDimPoint2;
//dxf文档中说标注点在第二根线上,不能由倾斜度纠正出标注点,
//因为autocad带倾斜的标注就没导出这个倾斜度
AcGeVector3d vBorderDir = m_ptDimLinePoint - m_ptDimPoint2;
vBorderDir.normalize();
//第一根界线
AcGePoint3d ptBorder1Start = m_ptDimPoint1 + vBorderDir * (m_dDIMSCALE*m_dDIMEXO);
AcGePoint3d ptBorder1End = m_ptDimPoint1 + vDimPtToDimLineOffset + vBorderDir *m_dDIMSCALE * m_dDIMEXE;
//第二根界线
AcGePoint3d ptBorder2Start = m_ptDimPoint2 + vBorderDir * (m_dDIMSCALE*m_dDIMEXO);
AcGePoint3d ptBorder2End = m_ptDimPoint2 + vDimPtToDimLineOffset + vBorderDir *m_dDIMSCALE * m_dDIMEXE;
osg::Geometry* pBorderLineGeom = new osg::Geometry();
osg::Vec3dArray* pVertexArray = new osg::Vec3dArray();
pVertexArray->push_back(osg::Vec3d(ptBorder1Start.x,
ptBorder1Start.y, ptBorder1Start.z));
pVertexArray->push_back(osg::Vec3d(ptBorder1End.x,
ptBorder1End.y, ptBorder1End.z));
pVertexArray->push_back(osg::Vec3d(ptBorder2Start.x,
ptBorder2Start.y, ptBorder2Start.z));
pVertexArray->push_back(osg::Vec3d(ptBorder2End.x,
ptBorder2End.y, ptBorder2End.z));
pBorderLineGeom->setVertexArray(pVertexArray);
pBorderLineGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,
0, pVertexArray->size()));
return pBorderLineGeom;
}
osg::ref_ptr<osg::Drawable> DrawerGMAlignedDimension::DrawArrow()
{
AcGeVector3d vDimPtToDimLineOffset = m_ptDimLinePoint - m_ptDimPoint2;标注点到标注线的偏移向量
//获取箭头大小
//箭头大小为长度,高度的一半为0.2*大小,若放不下,增加的引线长也为箭头长度即可。
double dArrowSize = m_dDIMASZ * m_dDIMSCALE;
//计算箭头水平、垂直方向需要的偏移向量
AcGeVector3d vDimLineDir = m_ptDimPoint2 - m_ptDimPoint1;//标注线方向
AcGeVector3d vArrowHOffset = vDimLineDir; //箭头水平方向
AcGeVector3d vArrowVOffset = vDimLineDir; //箭头垂直方向
vArrowVOffset.rotateBy(PI / 2.0, AcGeVector3d::kZAxis);
vArrowHOffset.normalize();
vArrowVOffset.normalize();
vArrowHOffset = vArrowHOffset * dArrowSize; //箭头水平偏移向量
vArrowVOffset = vArrowVOffset * dArrowSize * 0.2; //箭头垂直方向偏移向量
osg::Geometry* pArrowGeom = new osg::Geometry();
osg::Vec3dArray* pVertexArray = new osg::Vec3dArray();
//起点箭头
{
AcGePoint3d ptDimLineStart = m_ptDimPoint1 + vDimPtToDimLineOffset;//标注线起点
AcGePoint3d ptFirst, ptSencond, ptThird;
ptFirst = (ptDimLineStart + vArrowHOffset) + vArrowVOffset;
ptSencond = (ptDimLineStart + vArrowHOffset) - vArrowVOffset;
ptThird = ptDimLineStart;
pVertexArray->push_back( osg::Vec3d(ptFirst.x, ptFirst.y, ptFirst.z)); //start point
pVertexArray->push_back(osg::Vec3d(ptSencond.x, ptSencond.y, ptSencond.z)); //same as start point
pVertexArray->push_back(osg::Vec3d(ptThird.x, ptThird.y, ptThird.z));
}
//末点箭头
{
AcGePoint3d ptDimLineEnd = m_ptDimPoint2 + vDimPtToDimLineOffset;//标注线末点
AcGePoint3d ptFirst, ptSencond, ptThird;
ptFirst = (ptDimLineEnd - vArrowHOffset) + vArrowVOffset;
ptSencond = (ptDimLineEnd - vArrowHOffset) - vArrowVOffset;
ptThird = ptDimLineEnd;
pVertexArray->push_back(osg::Vec3d(ptFirst.x, ptFirst.y, ptFirst.z)); //start point
pVertexArray->push_back(osg::Vec3d(ptSencond.x, ptSencond.y, ptSencond.z)); //same as start point
pVertexArray->push_back(osg::Vec3d(ptThird.x, ptThird.y, ptThird.z));
}
pArrowGeom->setVertexArray(pVertexArray);
pArrowGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
0, pVertexArray->size()));
return pArrowGeom;
}
void DrawerGMAlignedDimension::DrawDimText(INT nModelFlag,
osg::ref_ptr<osg::Geode>& pRtOsgGeode)
{
if (!m_pGRSolidFactoryImp)
{
return;
}
//
//暂只实现了文字居中、放置上标注线上方的逻辑
//
//标注文字值,要处理使用测量值的情况
CString strDimText = m_strDimText;
if (strDimText.IsEmpty())//文字替换为空,则使用测量值
{
double dDistance = m_ptDimPoint1.distanceTo(m_ptDimPoint2);
switch (m_nDIMDEC)
{
case 0:
strDimText.Format(_T("%.0f"), dDistance);
break;
case 1:
strDimText.Format(_T("%.1f"), dDistance);
break;
case 2:
strDimText.Format(_T("%.2f"), dDistance);
break;
case 3:
strDimText.Format(_T("%.3f"), dDistance);
break;
case 4:
strDimText.Format(_T("%.4f"), dDistance);
break;
case 5:
strDimText.Format(_T("%.5f"), dDistance);
break;
case 6:
strDimText.Format(_T("%.6f"), dDistance);
break;
default:
strDimText.Format(_T("%.0f"), dDistance);
}
RemoveBackZero(strDimText);
}
//文字标注方向
AcGeVector3d vDimTextDir = (m_ptDimPoint2 - m_ptDimPoint1).normal();
//实现居中、上方的文字位置 shanql 2022.7.25
//文字延着标注线垂直方向向上偏移指定距离。
//标注线方向的确定: 标注方向 = 标注第二点 - 标注第一点
//1、使用点积判断
//若标注方向与x轴正向平行,标注方向取+x;
//否则,若标注方向与x轴垂直,标注方向取+y;
//否则,若标注方向与x轴点积 < 0, 则标注方向取反
//否则标注方向不变
//
//2、使用angleTo求出两向量[0-pi]的夹角
//若为0或pi,则表示与x轴平行,标注方向取+x
//否则若为pi/2, 则表示与x轴垂直,标注方向取+y;
//否则若>pi/2, 则标注方向取反
//否则标注方向不变
//ptTextPosTemp = ptDimMid + (m_dDIMGAP + m_dDIMTXT / 2.0) * m_dDIMSCALE * vecTextOffsetDir;
if (vDimTextDir.isCodirectionalTo(AcGeVector3d::kXAxis))
{//平行x轴
vDimTextDir = AcGeVector3d::kXAxis;
}
else if (vDimTextDir.isPerpendicularTo(AcGeVector3d::kXAxis))
{//垂直x轴
vDimTextDir = AcGeVector3d::kYAxis;
}
else
{
if (vDimTextDir.angleTo(AcGeVector3d::kXAxis) > PI / 2.0)
{
vDimTextDir = -vDimTextDir;
}
}
std::shared_ptr<GMText> pGMText = std::make_shared<GMText>(strDimText);
pGMText->SetExtendDir(vDimTextDir);
pGMText->SetNormal(AcGeVector3d::kZAxis);
AcGePoint3d ptTextPosTemp = m_ptTextPos;
if (ptTextPosTemp.isEqualTo(AcGePoint3d::kOrigin))
{
AcGeVector3d vecTextOffsetDir = vDimTextDir;
vecTextOffsetDir.rotateBy(PI / 2.0, AcGeVector3d::kZAxis);
//求出标注中点
AcGeVector3d vDimPtToDimLineOffset = m_ptDimLinePoint - m_ptDimPoint2;//标注点到标注线的偏移向量
AcGePoint3d ptDimLineStart = m_ptDimPoint1 + vDimPtToDimLineOffset;//标注线起点
AcGePoint3d ptDimLineEnd = m_ptDimPoint2 + vDimPtToDimLineOffset;//标注线末点
AcGePoint3d ptDimMid = (ptDimLineStart + ptDimLineEnd.asVector()) / 2.0;
//求出文字位置
ptTextPosTemp = ptDimMid + (m_dDIMGAP + m_dDIMTXT / 2.0) * m_dDIMSCALE * vecTextOffsetDir;
}
pGMText->SetPosition(ptTextPosTemp);//文字位置
pGMText->SetAttachment(GMText::AttachmentType::MiddleCenter);
double dTextHeight = m_dDIMTXT * m_dDIMSCALE;
pGMText->SetHeight(dTextHeight);//文字高度
pGMText->SetWidth(dTextHeight*1.0);
m_pGRSolidFactoryImp->Create(pGMText, nModelFlag, pRtOsgGeode);
}
运行截图
与autocad的对比图