效果如下:
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;
}
}