Revit二次开发-曲线三连:对curves进行排序

日常开发工作中,经常会遇到这样的场景:

通过手动选择(或其他手段),获取到了一些头尾相连的曲线List<Curves> curves(只限于Line和Arc),现在只知道它们是相连的,但是不知是否沿着一个方向,在集合中是否是按顺序排列?

可以根据以下方式对其进行排序,达到真正的首尾相连的结果:

1.首先我们找到第一根线L1,满足要求:有一端是没有其他线与其相重合的。并记录L1与其他线重合的那个端点PL1。

2.然后找下一根线,满足要求:有一端点与PL1重合,并记录另一端点P2;

3.重复第二步,直至最后一根线。

如此我们就可以保证所有曲线都是按照次序一根接着一根的。

贴代码(经测试,应该没问题,但很多地方可能有重复过程):

        /// <summary>
        /// 对目标曲线进行排序(只改变curves的顺序)
        /// </summary>
        /// <param name="curves"></param>
        /// <returns></returns>
        private List<Curve> OrderCurves(List<Curve> curves)
        {
            //如果只有1根或者2根,那么不需要排序
            if (curves.Count < 3)
            {
                return curves;
            }
            //首先找到第一根线
            Curve firstCurve = null;
            foreach (var curve in curves)
            {
                if (IsCurveJoinedBothPoints(curve, curves) == false)
                {
                    firstCurve = curve;
                    break;
                }
            }

            var orderedCurves = new List<Curve> { firstCurve };

            //然后从第二个元素开始,找与第一个元素首尾相连的对象
            for (int i = 0; i < orderedCurves.Count; i++)
            {
                foreach (var item in curves)
                {
                    //首先保证item并不在orderedCurves中
                    if (orderedCurves.Contains(item) == false)
                    {
                        //如果curves存在一根线与orderedCurves[i]的端点重合
                        if (IsPointJoinedWithCurve(orderedCurves[i].GetEndPoint(0), item, out _)
                            || IsPointJoinedWithCurve(orderedCurves[i].GetEndPoint(1), item, out _))
                        {
                            orderedCurves.Add(item);
                        }
                    }
                }
            }
            return orderedCurves;
        }

        /// <summary>
        /// 判断这根线的两个端点,是否与目标curves中的线都相连接
        /// </summary>
        /// <param name="curve"></param>
        /// <param name="curves"></param>
        /// <returns></returns>
        private bool IsCurveJoinedBothPoints(Curve curve, List<Curve> curves)
        {
            if (curves.Exists(
                x => x.GetHashCode() != curve.GetHashCode()//不是同一根线
                && IsPointJoinedWithCurve(curve.GetEndPoint(0), x, out _)//有线与curve的起点重合
                ))
            {
                if (curves.Exists(
                y => y.GetHashCode() != curve.GetHashCode()//不是同一根线
                && IsPointJoinedWithCurve(curve.GetEndPoint(1), y, out _)//也有线与curve的终点重合
                ))
                {
                    //即如果即有与curve起点重合的线,又有与curve重点重合的线
                    //就判定这跟线收尾都有与之相邻的线
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 判断一个点和一根线的起始点是否重合
        /// </summary>
        /// <param name="point"></param>
        /// <param name="curve"></param>
        /// <param name="p">0代表curve与point的起点重合,1代表curve与point的终点重合</param>
        /// <returns></returns>
        private bool IsPointJoinedWithCurve(XYZ point, Curve curve, out int p)
        {
            if (curve.GetEndPoint(0).DistanceTo(point)<_presion)
            {
                p = 0;
                return true;
            }
            else if (curve.GetEndPoint(1).DistanceTo(point) < _presion)
            {
                p = 1;
                return true;
            }
            p = -1;
            return false;
        }

        /// <summary>
        /// 对orderedCurves的第一条线做变向处理,使其开放端为起点
        /// </summary>
        /// <param name="curves"></param>
        private List<Curve> ChangeFirstCurveOrientation(List<Curve> curves)
        {
            var firstCurve = curves[0];
            //如果第一条线的起点,有其他线与之重合,则将第一条线的方向改一下
            if (curves.Exists(x=> x.GetHashCode()!= firstCurve.GetHashCode()&&
            IsPointJoinedWithCurve(firstCurve.GetEndPoint(0),x,out int _)))
            {
                var newCurve = firstCurve.CreateReversed();
                curves.Remove(firstCurve);
                curves.Insert(0, newCurve);
            }
            return curves;
        }

        /// <summary>
        /// 改变曲线的方向,使其首尾相连
        /// </summary>
        /// <param name="curves"></param>
        /// <returns></returns>
        private List<Curve> ChangeOriention(List<Curve> curves)
        {
            if (curves.Count < 2)
            {
                return curves;
            }
            var output = new List<Curve>() { curves[0] };
            for (int i = 1; i <curves.Count; i++)
            {
                var p0 = output[i - 1].GetEndPoint(0);
                var p1 = output[i - 1].GetEndPoint(1);

                var p10 = curves[i].GetEndPoint(0);
                var p11 = curves[i].GetEndPoint(1);
                //否则,就是起点与起点重合,终点与终点重合,需要改变其方向
                if (p0.DistanceTo(p10) < _presion || p1.DistanceTo(p11) < _presion)
                {
                    var curve = curves[i].CreateReversed();
                    output.Add(curve);
                }
                //如果下一根线与上一根线是起点与终点重合,或者终点与起点重合,说明方向一样
                //那就原封不动放进去
                else
                {
                    output.Add(curves[i]);
                }
            }
            return output;
        }

 

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值