• DXF笔记:多义线的绘制


    多义线凸度

    凸度值是多义线的当前顶点与下一个顶点之间的弧的1/4的正切。一个负的凸度值表示弧是以顺时针方向从选择的顶点至下一个顶点。反之,正的凸度值则是逆时针的方向。

    直线的生成算法思路

    凸度值为0的为直线段,直接两点生成直线即可

    弧线的生成算法思路

    假设第一点为A, 第二点为B, 第一点凸度为bulge
    Bulge为0时,是直线,不用处理。

    1. 计算出圆弧弧度
      弧度 = arctan( fabs(bulge)*4 )

    2. 计算圆弧法向量
      If( 凸度 > 0 ) normal=(0,0,1)
      else normal = (0,0,-1)

    3. 弧度为180度,圆心为A、B两点中心,构造圆弧信息已够,不用进行后续步骤。否则进入以下步骤。

    4. 计算出圆弧圆心
      大体思路是使用点A、B的中点,在AB的中垂线上偏移指定距离得到圆心,如下图:
      在这里插入图片描述

      求出A、B两点中点C
      若弧度大于180
      求出中点C到圆心的偏移距离Offset = distance(A,C) * cot(PI-弧度/2.0)
      求出偏移方向,(中点C-第一点A)绕轴normal旋转90度
      否则
      求出中点C到圆心的偏移距离Offset = distance(A,C) * cot(弧度/2.0)
      求出偏移方向,(中点C-第一点A)绕轴normal旋转-90度

      圆心 = 中点C + Offset * 偏移方向

    5. 求出圆弧
      ptCenter = 圆心
      vDir = normal
      dRadius = A.distanceTo(圆心)
      refVec = 点A - 圆心
      dAngleStart = 0
      dAngleEnd = 弧度

    示例代码

    使用osg绘制,使用objectArx的算法库

    		AcGePoint3dArray& mGMPtArray = pGMSymbolPloyline->GetPointArray();
    		if (mGMPtArray.length() <= 1)//至少要两个顶点
    		{
    			return;
    		}
    
    		AcGePoint3d ptFirst = mGMPtArray.at(0);
    		for (int i = 1; i < mGMPtArray.length(); ++i)
    		{
    			double dBugle = pGMSymbolPloyline->GetPtBugleAt(i-1);
    			const AcGePoint3d& ptSecond = mGMPtArray.at(i);
    			if (UK_DOUBLE_EQ(dBugle, 0.0)) //凸度为0,直线
    			{
    				osg::ref_ptr<osg::Geometry> pGeomLine = new osg::Geometry();
    				osg::ref_ptr<osg::Vec3dArray> pVertextArray = new osg::Vec3dArray();
    				pVertextArray->push_back(osg::Vec3d(ptFirst.x, ptFirst.y, ptFirst.z));
    				pVertextArray->push_back(osg::Vec3d(ptSecond.x, ptSecond.y, ptSecond.z));
    				pGeomLine->setVertexArray(pVertextArray);
    				pGeomLine->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,
    					0, pVertextArray->size()));
    				pRtOsgGeode->addDrawable(pGeomLine);
    			}
    			else //弧线
    			{
    				double dRadian = atan( fabs(dBugle)) * 4.0; //圆弧的弧度值
    				AcGeVector3d vecNormal = AcGeVector3d::kZAxis; //圆弧法向量
    				AcGePoint3d ptMiddle = (ptFirst + ptSecond.asVector()) / 2.0;
    				
    				if (UK_DOUBLE_LT(dBugle, 0.0))//负的凸度值表示弧是以顺时针方向从选择的顶点至下一个顶点
    				{
    					vecNormal = -vecNormal;
    				}
    
    				if (UK_DOUBLE_EQ(dRadian, PI))//==180度 半圆
    				{
    					//创建圆弧
    					AcGeVector3d refVec = ptFirst - ptMiddle;
    					auto pGMArc = std::make_shared<GMArc>(ptMiddle, 
    						vecNormal, 
    						refVec,
    						ptMiddle.distanceTo(ptFirst),
    						0.0, 
    						dRadian);
    					this->Create(pGMArc, nModelFalg, pRtOsgGeode);
    				}
    				else
    				{
    					AcGeVector3d offsetDir = ptFirst - ptMiddle;
    					offsetDir.normalize();
    					double dOffsetValue = 0.0;
    					if (UK_DOUBLE_GT(dRadian, PI)) //>180度,优弧
    					{
    						dOffsetValue = ptMiddle.distanceTo(ptFirst) / std::tan(PI - dRadian / 2.0);
    						offsetDir.rotateBy(PI / 2.0, vecNormal);
    					}
    					else //< 180度
    					{
    						dOffsetValue = ptMiddle.distanceTo(ptFirst) / std::tan(dRadian / 2.0);
    						offsetDir.rotateBy(-PI / 2.0, vecNormal);
    					}
    
    					//创建圆弧
    					
    					AcGePoint3d ptCenter = ptMiddle + dOffsetValue * offsetDir;
    					AcGeVector3d refVec = ptFirst - ptCenter;
    					auto pGMArc = std::make_shared<GMArc>(ptCenter, 
    						vecNormal, 
    						refVec,
    						ptCenter.distanceTo(ptFirst),
    						0.0, 
    						dRadian);
    					this->Create(pGMArc, nModelFalg, pRtOsgGeode);
    				}
    			}
    
    			ptFirst = ptSecond; //绘制下一根线
    		}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    运行及对比

    在这里插入图片描述

  • 相关阅读:
    Python实现 关联规则的Apriori 算法-亚马逊购物零售数据挖掘
    terraform简单的开始-vpc cvm创建
    [SWPUCTF 2022 新生赛]善哉善哉(隐写,新佛曰,MD5)
    python项目根据requirements.txt pip安装依赖
    LVS负载均衡群集(NAT模式、IP隧道模式、DR模式)
    Windows 根据dll生成 lib文件
    java Locale类使用
    优化 if-else 语句的最佳方案
    sed命令使用总结
    jQuery学习:显示隐藏 一级菜单
  • 原文地址:https://blog.csdn.net/s634772208/article/details/126270409