效果如下:
代码如下:
using IfoxDemo;
//[assembly: CommandClass(typeof(IFoxDemo.凸包class))]//只允许此类快捷键命令
namespace IFoxDemo
{public class 凸包class{public static class 凸包助手{/// <summary>/// 计算点集的凸包并返回多段线/// </summary>/// <param name="pts">点集合</param>/// <returns>凸包多段线</returns>public static Polyline 计算凸包(List<Point2d> pts){if (pts == null || pts.Count < 3){throw new ArgumentException("至少需要三个点来计算凸包。");}// 计算凸包点集List<Point2d> convexHullPoints = 筛选凸包点(pts);// 创建多段线Polyline convexHullPolyline = new Polyline();for (int i = 0; i < convexHullPoints.Count; i++){convexHullPolyline.AddVertexAt(i, convexHullPoints[i], 0, 0, 0);}// 闭合多段线convexHullPolyline.AddVertexAt(convexHullPoints.Count, convexHullPoints[0], 0, 0, 0);convexHullPolyline.Closed = true;return convexHullPolyline;}/// <summary>/// 使用 Andrew's monotone chain 算法计算凸包/// </summary>/// <param name="points">输入点集</param>/// <returns>凸包点集</returns>private static List<Point2d> 筛选凸包点(List<Point2d> points){// 按 X 坐标排序,如果 X 相同则按 Y 排序points.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X));List<Point2d> hull = new List<Point2d>();// 构建下凸包foreach (var pt in points){while (hull.Count >= 2 && Cross(hull[hull.Count - 2], hull[hull.Count - 1], pt) <= 0){hull.RemoveAt(hull.Count - 1);}hull.Add(pt);}// 构建上凸包int lowerHullCount = hull.Count + 1;for (int i = points.Count - 1; i >= 0; i--){var pt = points[i];while (hull.Count >= lowerHullCount && Cross(hull[hull.Count - 2], hull[hull.Count - 1], pt) <= 0){hull.RemoveAt(hull.Count - 1);}hull.Add(pt);}// 移除最后一个点,因为它是第一个点的重复hull.RemoveAt(hull.Count - 1);return hull;}/// <summary>/// 计算叉积/// </summary>/// <param name="O">起点</param>/// <param name="A">点 A</param>/// <param name="B">点 B</param>/// <returns>叉积值</returns>private static double Cross(Point2d O, Point2d A, Point2d B){return (A.X - O.X) * (B.Y - O.Y) - (A.Y - O.Y) * (B.X - O.X);}}public class 凸包Demo类{[CommandMethod("tub")]public void 凸包Demo(){Document doc = Application.DocumentManager.MdiActiveDocument;Database db = doc.Database;Editor ed = doc.Editor;var pts = new List<DBPoint>();if (! ed.GetEntities(out pts ,"") ) return;//List<Point2d> points = new List<Point2d>();//foreach (DBPoint p in pts)//{// points.Add(new Point2d(p.Position.X,p.Position.Y));//}下面为lambda等效写法List<Point2d> points = pts.Select(p => new Point2d(p.Position.X, p.Position.Y)).ToList();#region获取点集合(这里假设用户已经选择了一些点)//PromptPointOptions ppo = new PromptPointOptions("\n选择点: ");//ppo.AllowNone = false;//ppo.Keywords.Add("Done");//List<Point2d> points = new List<Point2d>();//while (true)//{// PromptPointResult ppr = ed.GetPoint(ppo);// if (ppr.Status == PromptStatus.Keyword && ppr.StringResult == "Done")// {// break;// }// points.Add(new Point2d(ppr.Value.X, ppr.Value.Y));//}//if (points.Count < 3)#endregionif (points.Count < 3){ed.WriteMessage("\n至少需要三个点来计算凸包。");return;}// 计算凸包Polyline pl = 凸包助手.计算凸包(points);// 将多段线添加到当前图形#region//using (Transaction tr = db.TransactionManager.StartTransaction())//{// BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;// BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;// btr.AppendEntity(convexHullPolyline);// tr.AddNewlyCreatedDBObject(convexHullPolyline, true);// tr.Commit();//}#endregionusing var dbtrans = new DBTrans();dbtrans.CurrentSpace.AddEntity(pl);ed.WriteMessage("\n凸包多段线已创建。");}}public class 产生随机点{[CommandMethod("cssjd")]public void CreateRandomPoints(){Document doc = Application.DocumentManager.MdiActiveDocument;Database db = doc.Database;Editor ed = doc.Editor;// 提示用户输入点的数量PromptIntegerOptions pio = new PromptIntegerOptions("\n请输入要创建的点数量: ");pio.AllowNegative = false;pio.AllowZero = false;pio.DefaultValue = 10;PromptIntegerResult pir = ed.GetInteger(pio);if (pir.Status != PromptStatus.OK){ed.WriteMessage("\n用户取消操作。");return;}int pointCount = pir.Value;// 提示用户输入随机点的范围PromptPointOptions ppo = new PromptPointOptions("\n指定随机点的范围(左下角点): ");PromptPointResult ppr1 = ed.GetPoint(ppo);if (ppr1.Status != PromptStatus.OK){ed.WriteMessage("\n用户取消操作。");return;}ppo.Message = "\n指定随机点的范围(右上角点): ";PromptPointResult ppr2 = ed.GetPoint(ppo);if (ppr2.Status != PromptStatus.OK){ed.WriteMessage("\n用户取消操作。");return;}Point3d lowerLeft = ppr1.Value;Point3d upperRight = ppr2.Value;// 创建随机点Random random = new Random();using (Transaction tr = db.TransactionManager.StartTransaction()){BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;for (int i = 0; i < pointCount; i++){double x = lowerLeft.X + (upperRight.X - lowerLeft.X) * random.NextDouble();double y = lowerLeft.Y + (upperRight.Y - lowerLeft.Y) * random.NextDouble();Point2d randomPoint2d = new Point2d(x, y);Point3d randomPoint3d = new Point3d(randomPoint2d.X, randomPoint2d.Y, 0);// 创建点实体DBPoint dbPoint = new DBPoint(randomPoint3d);btr.AppendEntity(dbPoint);tr.AddNewlyCreatedDBObject(dbPoint, true);}tr.Commit();}ed.WriteMessage($"\n成功创建 {pointCount} 个随机点。");}}}
}
逆时针最小夹角
cad 二次开发、插件代写↓↓↓