CAD二次开发获得多段线里的圆弧段的中点

多段线里的圆弧段:它的中点计算思路是

1)获得NumberOfSegments顶点数量

2)然后通过(polyline.GetSegmentType(i) == SegmentType.Arc判断是否为圆弧段

3)是的话,通过拿到它的CircularArc2d对象

4)通过CircularArc2d对象计算它的中点

cs 复制代码
 for (int i = 0; i < polyline.NumberOfSegments; i++)
                    {
                        if (polyline.GetSegmentType(i) == SegmentType.Arc)
                        {
                            Point2d arcStartPt = polyline.GetPoint2dAt(i);
                            Point2d arcEndPt = polyline.GetPoint2dAt(i + 1);
                            CircularArc2d circArc = polyline.GetArcSegmentAt(i) as CircularArc2d;

                            if (circArc == null)
                            {
                                ed.WriteMessage($"\n第{i+1}段圆弧转换失败!");
                                continue;
                            }

                            // 调用最终修正版函数
                            Point2d midPoint = CalculatePolylineArcMidpoint(circArc, arcStartPt, arcEndPt);

                            ed.WriteMessage($"\n=== 第{i+1}段圆弧 ===");
                            ed.WriteMessage($"\n起点: ({arcStartPt.X:F2},{arcStartPt.Y:F2})");
                            ed.WriteMessage($"\n终点: ({arcEndPt.X:F2},{arcEndPt.Y:F2})");
                            ed.WriteMessage($"\n中点: ({midPoint.X:F2},{midPoint.Y:F2})");

                            midPoints.Add(midPoint);
                        }
                    }

通过CircularArc2d对象计算它的中点,看似可以通过圆弧的几个参数进行计算,但是它有个大坑。就是拿到的起点角度一直都是0. 这也说明这是一个局部坐标系。

使用豆包进行分析,给出函数如下:

cs 复制代码
/// <summary>
        /// 最终修正版:适配多段线圆弧段(起点切线为局部0角度)的中点计算
        /// </summary>
        /// <param name="circArc">CircularArc2d对象</param>
        /// <param name="arcStartPt">圆弧段起点(全局)</param>
        /// <param name="arcEndPt">圆弧段终点(全局)</param>
        /// <returns>正确的圆弧中点(全局坐标)</returns>
        private Point2d CalculatePolylineArcMidpoint(CircularArc2d circArc, Point2d arcStartPt, Point2d arcEndPt)
        {
            // 步骤1:计算圆弧的弦向量(起点→终点)
            Vector2d chordVec = arcEndPt - arcStartPt;
            // 步骤2:计算起点处的法线向量(指向圆心)并单位化
            Vector2d normalVec = circArc.Center - arcStartPt;
            normalVec = normalVec.GetNormal();

            // 步骤3:计算起点切线方向(局部0角度)
            double tangentAngle = normalVec.Angle + Math.PI / 2; // 逆时针圆弧:法线逆时针转90°=切线
            if (circArc.IsClockWise)
            {
                tangentAngle = normalVec.Angle - Math.PI / 2; // 顺时针圆弧:法线顺时针转90°=切线
            }

            // 步骤4:转换局部角度到全局角度
            double globalStartAngle = tangentAngle + circArc.StartAngle;
            double globalEndAngle = tangentAngle + circArc.EndAngle;

            // 步骤5:处理角度跨边界
            if (circArc.IsClockWise && globalStartAngle < globalEndAngle)
            {
                globalStartAngle += 2 * Math.PI;
            }
            else if (!circArc.IsClockWise && globalEndAngle < globalStartAngle)
            {
                globalEndAngle += 2 * Math.PI;
            }

            // 步骤6:计算中点角度(归一化)
            double midAngle = (globalStartAngle + globalEndAngle) / 2;
            midAngle = midAngle % (2 * Math.PI);
            if (midAngle < 0) midAngle += 2 * Math.PI;

            // 步骤7:计算中点坐标(X/Y均正确)
            double midX = circArc.Center.X + circArc.Radius * Math.Cos(midAngle);
            double midY = circArc.Center.Y + circArc.Radius * Math.Sin(midAngle);

            return new Point2d(midX, midY);
        }

部分场景有计算错误的地方,实在没办法,还是找了cursor进行算法分析,一步到位就解决了。贴出正解:

cs 复制代码
/// <summary>
        /// 最终修正版:适配多段线圆弧段(起点切线为局部0角度)的中点计算
        /// </summary>
        /// <param name="circArc">CircularArc2d对象</param>
        /// <param name="arcStartPt">圆弧段起点(全局)</param>
        /// <param name="arcEndPt">圆弧段终点(全局)</param>
        /// <returns>正确的圆弧中点(全局坐标)</returns>
        static public Point2d CalculatePolylineArcMidpoint(CircularArc2d circArc, Point2d arcStartPt, Point2d arcEndPt)
        {
            // 问题分析:对于多段线的圆弧段,CircularArc2d.StartAngle 始终是0度(相对于局部坐标系),
            // 因此不能直接使用 StartAngle 和 EndAngle 来计算全局角度。
            // 正确的做法:直接通过起点和终点的全局坐标来计算它们在全局坐标系下的角度。

            // 步骤1:计算起点和终点相对于圆心的向量
            Vector2d startVec = arcStartPt - circArc.Center;
            Vector2d endVec = arcEndPt - circArc.Center;

            // 步骤2:计算起点和终点的全局角度(相对于圆心)
            double globalStartAngle = startVec.Angle;
            double globalEndAngle = endVec.Angle;

            // 步骤3:处理角度跨边界(确保角度区间正确)
            // 对于逆时针圆弧,起点角度应该小于终点角度
            // 对于顺时针圆弧,起点角度应该大于终点角度
            if (circArc.IsClockWise)
            {
                // 顺时针圆弧:起点角度 > 终点角度
                if (globalStartAngle < globalEndAngle)
                {
                    globalStartAngle += 2 * Math.PI;
                }
            }
            else
            {
                // 逆时针圆弧:起点角度 < 终点角度
                if (globalEndAngle < globalStartAngle)
                {
                    globalEndAngle += 2 * Math.PI;
                }
            }

            // 步骤4:计算中点角度(归一化)
            double midAngle = (globalStartAngle + globalEndAngle) / 2;
            // 归一化角度到 [0, 2π) 范围
            midAngle = midAngle % (2 * Math.PI);
            if (midAngle < 0) midAngle += 2 * Math.PI;

            // 步骤5:计算中点坐标(使用全局坐标系)
            double midX = circArc.Center.X + circArc.Radius * Math.Cos(midAngle);
            double midY = circArc.Center.Y + circArc.Radius * Math.Sin(midAngle);

            return new Point2d(midX, midY);
        }
相关推荐
老狼买了个克21 天前
Inventor 二次开发从入门到精通(12)高级应用
microsoft·二次开发·cad二次开发·机械设计·inventor·机械制造
白雪公主的后妈1 个月前
Auto CAD二次开发——Ribbon界面(1)
ribbon·c#·cad二次开发
白雪公主的后妈2 个月前
Auto CAD二次开发——文字样式
c#·cad二次开发·文字样式
白雪公主的后妈3 个月前
Auto CAD二次开发——多边形多段线
c#·cad二次开发·多边形
白雪公主的后妈3 个月前
Auto CAD二次开发——创建圆弧对象
c#·cad二次开发·创建圆弧对象
技术闲聊DD1 年前
CAD二次开发IFoxCAD框架系列(25)- 自动加载和初始化的使用
c#·cad二次开发·ifoxcad
技术闲聊DD1 年前
CAD二次开发IFoxCAD框架系列(19)-图层操作
c#·cad·cad二次开发·ifoxcad
技术闲聊DD1 年前
CAD二次开发IFoxCAD框架系列(17)-图元操作
cad·cad二次开发·ifox
xwLink19962 年前
vb.net&cad二开自学笔记1:万里长征第一步Hello CAD!
vb.net·cad二次开发