Bootstrap

寻找最短路径

效果如下:

namespace IFoxDemo
{
    public  static class Zdlj
    {
        //[CommandMethod("xxxx")]
        //public static void XXa()
        //{
        //    using var tr = new DBTrans();
        //    List<Curve> curs = new List<Curve>();
        //    tr.Editor.GetEntities<Curve>(out curs,"\n请选择:") ;
        //    线图 xt = new 线图(curs);

        //    "a".Print();
        //}
        public static bool IsEqualsPoint3d(this Point3d point1, Point3d point2, int decimalPlaces)
        {
            // 格式化坐标值,保留三位小数
            string x1Formatted = Math.Round(point1.X, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string y1Formatted = Math.Round(point1.Y, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string z1Formatted = Math.Round(point1.Z, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);

            string x2Formatted = Math.Round(point2.X, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string y2Formatted = Math.Round(point2.Y, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string z2Formatted = Math.Round(point2.Z, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);

            return (x1Formatted == x2Formatted) && (y1Formatted == y2Formatted) && (z1Formatted == z2Formatted);
        }
    }
    public class 线
    {
        public Curve cur;
        public 节点 A , B;
        public double weight;
        public 线(Curve cur)
        {
            this.cur = cur;
            this.weight = cur.GetLength();
        }
        public 节点 GetOther(节点 one)
        {
            if (one == A) return B;
            else if (one == B) return A;
            else throw new System.Exception("节点不属于此线");
        }
    }
    public class 节点
    {
        public Point3d pt;
        public List<线> 连接线 = new List<线> ();
        public bool 标记;
        public double dist;
        public 节点 前点;
        public 节点(Point3d pt)
        {
          this.pt = pt;
        }
    }
    public class 线图
    {
        List<线> 线s = new List<线>();
        List<节点> 节点s = new List<节点>();
        public List<Point3d> 点去重(List<Point3d> points)
        {
            if (points == null)
            {
                return new List<Point3d>(); ;
            }
            List<Point3d> result = new List<Point3d>();
            // 使用字典来辅助去重,以点的坐标字符串作为键(一种简单的标识唯一性的方式)
            Dictionary<string, bool> pointDict = new Dictionary<string, bool>();
            foreach (Point3d point in points)
            {
                // 将坐标值格式化为保留三位小数的字符串形式
                string xStr = point.X.ToString("F3", CultureInfo.InvariantCulture);
                string yStr = point.Y.ToString("F3", CultureInfo.InvariantCulture);
                string zStr = point.Z.ToString("F3", CultureInfo.InvariantCulture);
                string key = $"{xStr}_{yStr}_{zStr}";
                if (!pointDict.ContainsKey(key))
                {
                    pointDict.Add(key, true);
                    result.Add(point);
                }
            }
            return result;
        }
        public 线图(List<Curve>curs)
        {
            List<Point3d> pts1 = new List<Point3d> ();
            foreach (var c in curs)
            {
                pts1.Add (c.StartPoint);
                pts1.Add (c.EndPoint);
            }
            List<Point3d> pts =  点去重(pts1);
            foreach (var p in pts)
            {
                节点s.Add(new 节点(p));
            }
            foreach (var c in curs)
            {
                线s.Add(new 线(c));
            }
            foreach(var dd in 节点s)
            {
                var vv1 = from x in 线s
                          where x.A == null
                          where x.cur.StartPoint .IsEqualsPoint3d(dd.pt, 3)//保留3为小数
                          select x;
                foreach (var v in vv1)
                {
                    v.A = dd;
                    dd.连接线.Add(v);
                }
                var vv2 = from x in 线s
                          where x.B == null
                          where x.cur.EndPoint.IsEqualsPoint3d(dd.pt, 3)//保留3为小数
                          select x;
                foreach (var v in vv2)
                {
                    v.B = dd;
                    dd.连接线.Add(v);
                }
            }
        }
        线 GetFromAB(节点 d1, 节点 d2)
        {
            var vv = from x in 线s
                     where x.A == d1 && x.B == d2||x.A==d2 && x.B==d1
                     select x;
            if (vv.Count() > 0) return vv.First();
            else return null;
        }
        public void Dijkstra寻路(Point3d p1, Point3d p2)
        {
            foreach (var a in 节点s)
            {
                a.dist = double.MaxValue;
                a.标记 = false;
            }
            var aa = from a in 节点s orderby a.pt.DistanceTo(p1) select a;
            var bb = from a in 节点s orderby a.pt.DistanceTo(p2)select a;
            var A = aa.First();
            var B = bb.First();
            A.dist = 0;
            while (true)
            {
                var zuiduanvv = from a in 节点s where a.标记 == false orderby a.dist select a;
                if (zuiduanvv.Count() == 0) break;
                var zuiduan = zuiduanvv.First();
                zuiduan .标记 = true;
                foreach (var lj in zuiduan.连接线)
                {
                    var ot = lj.GetOther(zuiduan);
                    var dist = zuiduan.dist + lj.weight;
                    if(dist < ot.dist)
                    {
                        ot.dist = dist;
                        ot.前点 = zuiduan;
                    }
                }
            }
            List<Curve> curs = new List<Curve>();
            var dq = B;
            while (true)
            {
                if (dq.前点!=null)
                {
                    var xx = GetFromAB(dq,dq.前点);
                    curs.Add(xx.cur);
                    dq = dq.前点;
                }
                else break;
            }
            foreach (var c in curs)
            {
                c.ColorIndex = 1;
            }
            Polyline pl = Swxl.JoinCurves(curs).First() as Polyline;
            if (pl is null) return;
            pl.ConstantWidth = 3;
            pl.ColorIndex= 1;
            using var tr = new DBTrans();
            tr.ModelSpace.AddEntity (pl);
            //tr.ModelSpace.AddEntity(curs);//ifox封装
        }

    }

}

 下面为早期版本

public class Testenv
{
    [CommandMethod(nameof(XX))]
    public void XX()
    {
        using var tr = new DBTrans();
        List<Curve> curs = new List<Curve>();
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Editor ed = doc.Editor;
       
        if (!ed.GetEntities<Curve>(out curs, "\n请选择:")) return;
        List<Curve> curs1 = new List<Curve>();
        foreach (Curve cur in curs)
        {
            var a = (Curve)cur.Clone();
            curs1.Add(a);
        }
        线图 xt = new 线图(curs1);
        Point3d pt1 = new Point3d();
        Point3d pt2 = new Point3d();
        ed.GetPoint(out pt1,"");
        ed.GetPoint(out pt2, "");
        xt.Dijkstra寻路(pt1,pt2);
        "a".Print(); 
    }
}
namespace IFoxDemo
{
    public  static class Zdlj
    {
        //[CommandMethod("xxxx")]
        //public static void XXa()
        //{
        //    using var tr = new DBTrans();
        //    List<Curve> curs = new List<Curve>();
        //    tr.Editor.GetEntities<Curve>(out curs,"\n请选择:") ;
        //    线图 xt = new 线图(curs);

        //    "a".Print();
        //}
        public static bool IsEqualsPoint3d(this Point3d point1, Point3d point2, int decimalPlaces)
        {
            // 格式化坐标值,保留三位小数
            string x1Formatted = Math.Round(point1.X, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string y1Formatted = Math.Round(point1.Y, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string z1Formatted = Math.Round(point1.Z, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);

            string x2Formatted = Math.Round(point2.X, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string y2Formatted = Math.Round(point2.Y, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);
            string z2Formatted = Math.Round(point2.Z, decimalPlaces).ToString($"F{decimalPlaces}", CultureInfo.InvariantCulture);

            return (x1Formatted == x2Formatted) && (y1Formatted == y2Formatted) && (z1Formatted == z2Formatted);
        }
    }
    public class 线
    {
        public Curve cur;
        public 节点 A , B;
        public double weight;
        public 线(Curve cur)
        {
            this.cur = cur;
            this.weight = cur.GetLength();
        }
        public 节点 GetOther(节点 one)
        {
            if (one == A) return B;
            else if (one == B) return A;
            else throw new System.Exception("节点不属于此线");
        }
    }
    public class 节点
    {
        public Point3d pt;
        public List<线> 连接线 = new List<线> ();
        public bool 标记;
        public double dist;
        public 节点 前点;
        public 节点(Point3d pt)
        {
          this.pt = pt;
        }
    }
    public class 线图
    {
        List<线> 线s = new List<线>();
        List<节点> 节点s = new List<节点>();
        public List<Point3d> 点去重(List<Point3d> points)
        {
            if (points == null)
            {
                return new List<Point3d>(); ;
            }
            List<Point3d> result = new List<Point3d>();
            // 使用字典来辅助去重,以点的坐标字符串作为键(一种简单的标识唯一性的方式)
            Dictionary<string, bool> pointDict = new Dictionary<string, bool>();
            foreach (Point3d point in points)
            {
                // 将坐标值格式化为保留三位小数的字符串形式
                string xStr = point.X.ToString("F3", CultureInfo.InvariantCulture);
                string yStr = point.Y.ToString("F3", CultureInfo.InvariantCulture);
                string zStr = point.Z.ToString("F3", CultureInfo.InvariantCulture);
                string key = $"{xStr}_{yStr}_{zStr}";
                if (!pointDict.ContainsKey(key))
                {
                    pointDict.Add(key, true);
                    result.Add(point);
                }
            }
            return result;
        }
        public 线图(List<Curve>curs)
        {
            List<Point3d> pts1 = new List<Point3d> ();
            foreach (var c in curs)
            {
                pts1.Add (c.StartPoint);
                pts1.Add (c.EndPoint);
            }
            List<Point3d> pts =  点去重(pts1);
            foreach (var p in pts)
            {
                节点s.Add(new 节点(p));
            }
            foreach (var c in curs)
            {
                线s.Add(new 线(c));
            }
            foreach(var dd in 节点s)
            {
                var vv1 = from x in 线s
                          where x.A == null
                          where x.cur.StartPoint .IsEqualsPoint3d(dd.pt, 3)//保留3为小数
                          select x;
                foreach (var v in vv1)
                {
                    v.A = dd;
                    dd.连接线.Add(v);
                }
                var vv2 = from x in 线s
                          where x.B == null
                          where x.cur.EndPoint.IsEqualsPoint3d(dd.pt, 3)//保留3为小数
                          select x;
                foreach (var v in vv2)
                {
                    v.B = dd;
                    dd.连接线.Add(v);
                }
            }
        }
        线 GetFromAB(节点 d1, 节点 d2)
        {
            var vv = from x in 线s
                     where x.A == d1 && x.B == d2||x.A==d2 && x.B==d1
                     select x;
            if (vv.Count() > 0) return vv.First();
            else return null;
        }
        public void Dijkstra寻路(Point3d p1, Point3d p2)
        {
            foreach (var a in 节点s)
            {
                a.dist = double.MaxValue;
                a.标记 = false;
            }
            var aa = from a in 节点s orderby a.pt.DistanceTo(p1) select a;
            var bb = from a in 节点s orderby a.pt.DistanceTo(p2)select a;
            var A = aa.First();
            var B = bb.First();
            A.dist = 0;
            while (true)
            {
                var zuiduanvv = from a in 节点s where a.标记 == false orderby a.dist select a;
                if (zuiduanvv.Count() == 0) break;
                var zuiduan = zuiduanvv.First();
                zuiduan .标记 = true;
                foreach (var lj in zuiduan.连接线)
                {
                    var ot = lj.GetOther(zuiduan);
                    var dist = zuiduan.dist + lj.weight;
                    if(dist < ot.dist)
                    {
                        ot.dist = dist;
                        ot.前点 = zuiduan;
                    }
                }
            }
            List<Curve> curs = new List<Curve>();
            var dq = B;
            while (true)
            {
                if (dq.前点!=null)
                {
                    var xx = GetFromAB(dq,dq.前点);
                    curs.Add(xx.cur);
                    dq = dq.前点;
                }
                else break;
            }
            foreach (var c in curs)
            {
                c.ColorIndex = 1;
            }
           // var pl = 首尾相连.连续的线连成多段线(curs, 0.001) as Polyline;
            //pl.ConstantWidth = 30;
            //pl.ColorIndex = 1;
            using var tr = new DBTrans();
            //tr.ModelSpace .AddEntity (pl);
            tr.ModelSpace.AddEntity(curs);
        }

    }

}

封装

    public static bool GetEntities<T>(this Editor ed, out List<T> lists, string message) where T : Entity
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        //List<ObjectId> objectIds = new List<ObjectId>();
        List<T> tempCurves = new List<T>();
        PromptSelectionOptions pso = new PromptSelectionOptions();
        pso.MessageForAdding = message;
        pso.AllowDuplicates = true;
        PromptSelectionResult psr = ed.GetSelection(pso);
        if (psr.Status == PromptStatus.OK)
        {
            List<T> result = new List<T>();
            //SelectionSet selectionSet = psr.Value;
            ObjectId[] objs = psr.Value.GetObjectIds();
            using (Transaction tran = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
            {
                foreach (var item in objs)
                {
                    T entity = item.GetObject(OpenMode.ForRead) as T;
                    if (entity is T)
                    {
                        result.Add(entity as T);
                    }
                }
            }
            lists = result;
            int a = result.Count;
            return a > 0;
        }
        else
        {
            lists = null;
            return false;
        }

    }

  public static bool GetPoint(this Editor ed, out Point3d point, string message)
  {
      PromptPointResult pr;
      PromptPointOptions ps = new PromptPointOptions(message);
      pr = ed.GetPoint(ps);
      if (pr.Status == PromptStatus.OK)
      {
          point = pr.Value;
          return true;
      }
      else
      {
          ed.WriteMessage("\n用户取消了点的选择.");
          point = pr.Value;
          return false;
      }
  }

;