CAD面域转多段线

CAD中面域转多段线的主要思路是,首先把面域分解为若干个线条,然后把这些线条根据算法来首尾相连排序,最后,再获取所有曲线的节点,创建新的闭合多段线。全部代码如下

#region 面域转多段线-全新的正确算法

#region 面域转多段线调用
/// <summary>
/// 面域转多段线调用入口
/// </summary>
/// <param name="regList">面域列表</param>
/// <param name="gap">容差</param>
/// <param name="isPLClosed">多段线是否闭合</param>
/// <param name="pLColorInex">多段线颜色,默认与面域同色</param>
/// <returns></returns>
public static List<Polyline> GetPolylineFromRegion(this List<Region> regList, double gap, bool isPLClosed, int pLColorInex = -1)
{
    List<Polyline> newPLList = new List<Polyline>();
    if (regList.Count > 0)
    {
        for (int i = 0; i < regList.Count; i++)
        {
            Region rg = regList[i] as Region;

            DBObjectCollection dbcoll = new DBObjectCollection();
            rg.Explode(dbcoll);
            List<Entity> curveList = new List<Entity>();
            foreach (Entity item in dbcoll)
            {
                curveList.Add(item);
            }

            List<List<Entity>> GetConnectCueveGroupList = curveList.ConnectCurves(gap);
            List<Polyline> GetConnectPLList = GetConnectCueveGroupList.CreatePLFromCurveGroup(gap, true);

            if (pLColorInex < 0)
            {
                GetConnectPLList.ForEach(e => e.ColorIndex = rg.ColorIndex);
            }
            else
            {
                GetConnectPLList.ForEach(e => e.ColorIndex = pLColorInex);
            }

            GetConnectPLList.ForEach(e => e.Layer = rg.Layer);
            GetConnectPLList.ForEach(e => newPLList.Add(e));

        }
    }

    return newPLList;
}
#endregion

#region 相连曲线分组
// 扩展方法 ConnectCurves 用于曲线连接,传入曲线列表和允许的最小间隙 gap
public static List<List<Entity>> ConnectCurves(this List<Entity> curList, double gap)
{
    // 存储所有分组后的曲线集合
    List<List<Entity>> groupedCurves = new List<List<Entity>>();

    // 存储未处理的曲线,克隆以避免修改原始数据
    List<Entity> unprocessedCurves = curList.Select(curve => (Entity)curve.Clone()).ToList();

    // 迭代处理所有未处理的曲线
    while (unprocessedCurves.Count > 0)
    {
        // 当前分组
        List<Entity> currentGroup = new List<Entity>();

        // 从未处理曲线列表中取出一条曲线开始分组
        Entity currentCurve = unprocessedCurves[0];
        currentGroup.Add(currentCurve);
        unprocessedCurves.RemoveAt(0);

        bool curveAdded;
        do
        {
            curveAdded = false;

            // 遍历剩余未处理的曲线,尝试连接
            for (int i = unprocessedCurves.Count - 1; i >= 0; i--)
            {
                Entity nextCurve = unprocessedCurves[i];
                if (CanConnect(currentCurve, nextCurve, gap))
                {
                    // 将下一条曲线添加到当前分组
                    currentGroup.Add(nextCurve);
                    unprocessedCurves.RemoveAt(i);
                    currentCurve = nextCurve;
                    curveAdded = true;
                    break;
                }
                else if (CanConnect(currentCurve, nextCurve, gap, true))
                {
                    // 如果需要,反转曲线以匹配端点
                    ReverseCurve(nextCurve);
                    currentGroup.Add(nextCurve);
                    unprocessedCurves.RemoveAt(i);
                    currentCurve = nextCurve;
                    curveAdded = true;
                    break;
                }
            }

        } while (curveAdded);

        // 将当前分组添加到分组结果中
        groupedCurves.Add(currentGroup);
    }

    return groupedCurves;
}

// 检查两条曲线是否可以连接
private static bool CanConnect(Entity curve1, Entity curve2, double gap, bool allowReverse = false)
{
    Point3d endPoint1 = GetEndPoint(curve1);
    Point3d startPoint2 = GetStartPoint(curve2);

    if (endPoint1.DistanceTo(startPoint2) <= gap)
    {
        return true;
    }

    // 检查是否需要反转其中一条曲线
    if (allowReverse)
    {
        Point3d reversedStart2 = GetEndPoint(curve2);
        if (endPoint1.DistanceTo(reversedStart2) <= gap)
        {
            return true;
        }
    }

    return false;
}

// 获取曲线的起点
private static Point3d GetStartPoint(Entity curve)
{
    if (curve is Curve c)
    {
        return c.StartPoint;
    }
    throw new ArgumentException("实体不是曲线类型");
}

// 获取曲线的终点
private static Point3d GetEndPoint(Entity curve)
{
    if (curve is Curve c)
    {
        return c.EndPoint;
    }
    throw new ArgumentException("实体不是曲线类型");
}

// 反转曲线的首尾
private static void ReverseCurve(Entity curve)
{
    if (curve is Polyline polyline)
    {
        polyline.ReverseCurve();
    }
    else if (curve is Spline spline)
    {
        spline.ReverseCurve();
    }
    else if (curve is Arc arc)
    {
        arc.ReverseCurve();
    }
    else if (curve is Line line)
    {
        //Line reversedLine = new Line(line.EndPoint, line.StartPoint);
        //line = reversedLine;
        line.ReverseCurve();
    }
}

#endregion

#region 相连曲线生成完整多段线
// 扩展方法:从曲线组创建多段线
public static List<Entity> CreatePLFromCurveGroup(this List<List<Entity>> groupedCurves, double tolerance, bool closedPL)
{
    List<Entity> polylines = new List<Entity>();

    foreach (var group in groupedCurves)
    {
        if (group.Count == 1)
        {
            polylines.Add(group[0].Clone() as Entity);
        }
        else
        {
            // 创建一个新的多段线
            Polyline polyline = new Polyline();

            // 定义当前多段线的顶点索引
            int vertexIndex = 0;

            foreach (Entity entity in group)
            {
                if (entity is Line line)
                {
                    // 直线:添加起点和终点
                    polyline.AddVertexAt(vertexIndex++, To2D(line.StartPoint), 0, 0, 0);
                    polyline.AddVertexAt(vertexIndex++, To2D(line.EndPoint), 0, 0, 0);

                }
                else if (entity is Polyline pl)
                {
                    // 多段线:获取所有顶点
                    for (int i = 0; i < pl.NumberOfVertices; i++)
                    {
                        polyline.AddVertexAt(vertexIndex++, pl.GetPoint2dAt(i), pl.GetBulgeAt(i), pl.GetStartWidthAt(i), pl.GetEndWidthAt(i));
                    }

                }
                else if (entity is Arc arc)
                {
                    // 圆弧:添加起点和终点,并计算凸度
                    polyline.AddVertexAt(vertexIndex++, To2D(arc.StartPoint), 0, 0, 0);
                    polyline.AddVertexAt(vertexIndex++, To2D(arc.EndPoint), GetArcBulge(arc), 0, 0);

                }
                else if (entity is Spline spline)
                {
                    // 样条曲线:根据公差取样点
                    var splinePoints = spline.GetSamplePoints(tolerance);
                    foreach (var point in splinePoints)
                    {
                        polyline.AddVertexAt(vertexIndex++, To2D(point), 0, 0, 0);
                    }
                }

            }

            // 设置多段线是否闭合
            polyline.Closed = closedPL;

            // 将生成的多段线添加到结果列表中
            polylines.Add(polyline);
        }



    }

    return polylines;
}

// 将 3D 点转换为 2D 点
private static Point2d To2D(Point3d point)
{
    return new Point2d(point.X, point.Y);
}

// 计算圆弧的凸度
private static double GetArcBulge(Arc arc)
{
    double angle = arc.TotalAngle;
    return Math.Tan(angle / 4);
}

// 扩展方法:根据样条曲线获取采样点(示例实现)
private static List<Point3d> GetSamplePoints(this Spline spline, double tolerance)
{
    // 示例:根据公差获取样条曲线的采样点,实际代码可以更复杂
    List<Point3d> samplePoints = new List<Point3d>();

    // 样条曲线的起点
    samplePoints.Add(spline.StartPoint);

    // 使用曲线的长度和公差计算出多个取样点
    double length = spline.GetDistAtPoint(spline.EndPoint);
    int numPoints = (int)(length / tolerance);
    for (int i = 1; i < numPoints; i++)
    {
        double param = i / (double)numPoints * spline.EndParam;
        samplePoints.Add(spline.GetPointAtParameter(param));
    }

    // 样条曲线的终点
    samplePoints.Add(spline.EndPoint);

    return samplePoints;
}
#endregion

#endregion

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CNET99

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值