明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1145|回复: 4

[【PyCAD】] 构图及Astar 算法寻路

[复制链接]
发表于 2024-1-17 13:56:05 | 显示全部楼层 |阅读模式
本帖最后由 枫叶棋语 于 2024-1-17 23:08 编辑

  1. using CsCad.Collections;
  2. using CsCad.FlashDraw;
  3. using static CsCad.Draw.DrawEntity;
  4. namespace CsCad.PathSearch
  5. {
  6.     public class Edge2D
  7.     {
  8.         public Point2d StartPoint;
  9.         public Point2d EndPoint;
  10.         public double Dist;
  11.         public Polyline Polyline;
  12.         public Edge2D(Line line)
  13.         {
  14.             this.StartPoint = new Point2d(Math.Round( line.StartPoint.X,3),Math.Round( line.StartPoint.Y,3));
  15.             this.EndPoint = new Point2d(Math.Round( line.EndPoint.X,3),Math.Round( line.EndPoint.Y,3));
  16.             //this.Dist = Math.Abs(this.StartPoint.X - this.EndPoint.X) + Math.Abs(this.StartPoint.Y - this.EndPoint.Y);
  17.             this.Dist = this.StartPoint.GetDistanceTo(this.EndPoint);
  18.             this.Polyline = CreatePolyline(this.StartPoint, this.EndPoint);
  19.             this.Polyline.ColorIndex = 8;
  20.         }
  21.         public Edge2D(Point2d start, Point2d end)
  22.         {
  23.             this.StartPoint = new Point2d(Math.Round(start.X, 3), Math.Round(start.Y, 3));
  24.             this.EndPoint = new Point2d(Math.Round(end.X, 3), Math.Round(end.Y, 3));
  25.             //this.Dist = Math.Abs(this.StartPoint.X - this.EndPoint.X) + Math.Abs(this.StartPoint.Y - this.EndPoint.Y);
  26.             this.Dist = this.StartPoint.GetDistanceTo(this.EndPoint);
  27.             this.Polyline = CreatePolyline(this.StartPoint, this.EndPoint);
  28.             this.Polyline.ColorIndex = 8;
  29.         }
  30.         public Edge2D(Point3d start, Point3d end)
  31.         {
  32.             this.StartPoint = new Point2d(Math.Round(start.X, 3), Math.Round(start.Y, 3));
  33.             this.EndPoint = new Point2d(Math.Round(end.X, 3), Math.Round(end.Y, 3));
  34.             //this.Dist = Math.Abs(this.StartPoint.X - this.EndPoint.X) + Math.Abs(this.StartPoint.Y - this.EndPoint.Y);
  35.             this.Dist = this.StartPoint.GetDistanceTo(this.EndPoint);
  36.             this.Polyline = CreatePolyline(this.StartPoint, this.EndPoint);
  37.             this.Polyline.ColorIndex = 8;
  38.         }
  39.         public Point2d? GetNeighbor(Point2d current)
  40.         {
  41.             if (current == StartPoint)
  42.             {
  43.                 return EndPoint;
  44.             }
  45.             else if (current == EndPoint)
  46.             {
  47.                 return StartPoint;
  48.             }
  49.             else
  50.             {
  51.                 return null;
  52.             }
  53.         }
  54.         public override string ToString()
  55.         {
  56.             return $"[{this.StartPoint},{this.EndPoint}]";
  57.         }
  58.     }

  59.     public class Graphs2D
  60.     {
  61.         public DefaultDict<Point2d, HashSet<Edge2D>> Pairs;
  62.         public Flash Flash;
  63.         public List<Polyline> pls = new List<Polyline>();
  64.         public Graphs2D(HashSet<Line> lines)
  65.         {
  66.             this.Pairs = new DefaultDict<Point2d, HashSet<Edge2D>>();
  67.             Flash = new Flash();
  68.             var edges = lines.Select(line => new Edge2D(line)).ToList();
  69.             foreach (Edge2D edge in edges)
  70.             {
  71.                 this.Pairs[edge.StartPoint].Add(edge);
  72.                 this.Pairs[edge.EndPoint].Add(edge);
  73.             }

  74.         }
  75.         public Graphs2D(HashSet<Edge2D> edges)
  76.         {
  77.             this.Pairs = new DefaultDict<Point2d, HashSet<Edge2D>>();
  78.             Flash = new Flash();
  79.             foreach (Edge2D edge in edges)
  80.             {
  81.                 this.Pairs[edge.StartPoint].Add(edge);
  82.                 this.Pairs[edge.EndPoint].Add(edge);

  83.             }
  84.         }

  85.         public Graphs2D()
  86.         {
  87.             this.Pairs = new DefaultDict<Point2d, HashSet<Edge2D>>();
  88.             Flash = new Flash();
  89.         }
  90.         public void AddEdge(Edge2D edge)
  91.         {
  92.             this.Pairs[edge.StartPoint].Add(edge);
  93.             this.Pairs[edge.EndPoint].Add(edge);
  94.         }
  95.         public void AddLine(Line line)
  96.         {
  97.             var edge = new Edge2D(line);
  98.             AddEdge(edge);

  99.         }


  100.         public List<Point2d> AstarSearch(Point2d start, Point2d end)
  101.         {
  102.             start = new Point2d(Math.Round(start.X, 3), Math.Round(start.Y, 3));
  103.             end = new Point2d(Math.Round(end.X, 3), Math.Round(end.Y, 3));
  104.             List<Point2d> path = new List<Point2d>();
  105.             PriorityQueue2D<Point2d> queue = new PriorityQueue2D<Point2d>();
  106.             Dictionary<Point2d, Point2d> previous = new Dictionary<Point2d, Point2d>();
  107.             Dictionary<Point2d, double> distance = new Dictionary<Point2d, double>();
  108.             queue.Enqueue(start, 0);
  109.             distance[start] = 0;
  110.             var pl = new Polyline();
  111.             pl.ColorIndex = 1;
  112.             if (!Pairs.ContainsKey(start) || !Pairs.ContainsKey(end))
  113.             {
  114.                 // 起点或终点不在Pairs的key里面,返回空路径
  115.                 Print(Pairs.ContainsKey(start), Pairs.ContainsKey(end));
  116.                 Flash.Clear();
  117.                 return path;
  118.             }
  119.             while (queue.Count > 0)
  120.             {
  121.                 Point2d current = queue.Dequeue();
  122.                 int vertext = 0;
  123.                 if (current.Equals(end))
  124.                 {
  125.                     Flash.Clear();
  126.                     Flash.Update(pl);
  127.                     path.Add(current);
  128.                     pl.AddVertexAt(vertext, current, 0, 0, 0);
  129.                     while (previous.ContainsKey(current))
  130.                     {
  131.                         current = previous[current];
  132.                         vertext++;
  133.                         pl.AddVertexAt(vertext, current, 0, 0, 0);
  134.                         Flash.Update(pl, 1);
  135.                         path.Insert(0, current);
  136.                     }
  137.                     Flash.Clear();
  138.                     return path;
  139.                 }
  140.                 if (!this.Pairs.ContainsKey(current)) continue;
  141.                 HashSet<Edge2D> neighborEdges = this.Pairs[current];
  142.                 foreach (Edge2D neighborEdge in neighborEdges)
  143.                 {
  144.                     double dist = distance[current] + neighborEdge.Dist;
  145.                     var nextPoint = neighborEdge.GetNeighbor(current);
  146.                     switch (nextPoint)
  147.                     {
  148.                         case null:
  149.                             neighborEdge.Polyline.ColorIndex = 2;
  150.                             Flash.Update(neighborEdge.Polyline);
  151.                             Print(current);
  152.                             continue;
  153.                         default:
  154.                             if (!distance.ContainsKey(nextPoint.Value) || dist < distance[nextPoint.Value])
  155.                             {
  156.                                 neighborEdge.Polyline.ColorIndex = 6;
  157.                                 Flash.Update(neighborEdge.Polyline);
  158.                                 distance[nextPoint.Value] = dist;
  159.                                 previous[nextPoint.Value] = current;
  160.                                 double heuristic = CalculateHeuristic2D(nextPoint.Value, end);
  161.                                 double priority = dist + heuristic;
  162.                                 queue.Enqueue(nextPoint.Value, priority);
  163.                             }
  164.                             else if (distance.ContainsKey(nextPoint.Value))
  165.                             {
  166.                                 neighborEdge.Polyline.ColorIndex = 5;
  167.                                 Flash.Update(neighborEdge.Polyline);
  168.                             }

  169.                             break;
  170.                     }

  171.                 }
  172.             }
  173.             Flash.Clear();
  174.             return path;
  175.         }

  176.         private double CalculateHeuristic2D(Point2d current, Point2d end)
  177.         {

  178.             //return current.GetDistanceTo(end);
  179.             return Math.Abs(current.X - end.X) + Math.Abs(current.Y - end.Y);
  180.         }
  181.         public class PriorityQueue2D<T>
  182.         {
  183.             private List<PriorityQueueElement<T>> elements = new List<PriorityQueueElement<T>>();
  184.             private int counter = 0;

  185.             public int Count => elements.Count;

  186.             public void Enqueue(T item, double priority)
  187.             {
  188.                 elements.Add(new PriorityQueueElement<T>(item, priority, counter));
  189.                 counter++;
  190.                 elements.Sort();
  191.             }

  192.             public T Dequeue()
  193.             {
  194.                 var item = elements[0];
  195.                 elements.RemoveAt(0);
  196.                 return item.Value;
  197.             }
  198.         }

  199.         public class PriorityQueueElement<T> : IComparable<PriorityQueueElement<T>>
  200.         {
  201.             public T Value { get; }
  202.             public double Priority { get; }
  203.             public int Counter { get; }

  204.             public PriorityQueueElement(T value, double priority, int counter)
  205.             {
  206.                 Value = value;
  207.                 Priority = priority;
  208.                 Counter = counter;
  209.             }

  210.             public int CompareTo(PriorityQueueElement<T> other)
  211.             {
  212.                 int priorityComparison = Priority.CompareTo(other.Priority);
  213.                 if (priorityComparison != 0)
  214.                     return priorityComparison;
  215.                 else
  216.                     return Counter.CompareTo(other.Counter);
  217.             }
  218.         }
  219.       
  220.     }
  221. }

发表于 2024-1-20 18:58:59 | 显示全部楼层
跟你提一个你可能一直没有意识到的问题,Edge2D这个类看起来就是一个Rect,而你插入了很多字段,使得这个信息熵特别大,我可以很明确告诉你,信息熵特别大的类跑起来会很慢.
所以这个类只需要留下四个double...但是你保留了3小数,所以用float就好了.如果还有旋转的话,就只需要加个angle.
而距离和PL类,这些不应该持有字段,而是方法To出来就好了.
 楼主| 发表于 2024-1-22 08:32:58 | 显示全部楼层
你有种再说一遍 发表于 2024-1-20 18:58
跟你提一个你可能一直没有意识到的问题,Edge2D这个类看起来就是一个Rect,而你插入了很多字段,使得这个信息 ...

Edge2d 是边
发表于 2024-1-22 22:34:06 | 显示全部楼层
本帖最后由 你有种再说一遍 于 2024-1-22 22:35 编辑

是边的话...这个类型的意义就更小了...
你想想看,一个类型的构造函数传入一个line,然后转为pline,然后...万一后续判断我又不想要这个边了,不就是白转换了吗...这就为什么很多c++类采取半构造的原因.
而且你都能写那么复杂的功能了,要考虑一下性能了.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 03:30 , Processed in 0.627696 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表