From bf4a8bdbca911a705a5d1e1f64ed9626f51c65f5 Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Sun, 2 Feb 2025 12:01:47 +0000 Subject: [PATCH] =?UTF-8?q?update=20src/CADShared/ExtensionMethod/Geomerty?= =?UTF-8?q?/GeometryEx.cs.=20=E4=BF=AE=E5=A4=8D=E5=8E=9F=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=85=B1=E7=BA=BF=E7=82=B9=E5=8F=8A?= =?UTF-8?q?=E4=BC=A0=E5=85=A5=E7=9A=84=E7=82=B9=E9=9B=86=E5=A6=82=E6=9E=9C?= =?UTF-8?q?=E6=9C=89=E9=87=8D=E7=82=B9=E6=97=B6=E7=94=9F=E6=88=90=E7=9A=84?= =?UTF-8?q?=E5=87=B8=E5=8C=85=E5=8F=AF=E8=83=BD=E4=BC=9A=E6=9C=89=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E6=83=85=E5=86=B5=EF=BC=88=E5=85=B6=E5=AE=9E?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E4=B8=8E=E5=8E=9F=E6=9D=A5=E7=9A=84=E4=B8=80?= =?UTF-8?q?=E6=A0=B7=EF=BC=8C=E6=B2=A1=E6=9C=89=E5=8E=BB=E6=B7=B1=E7=A9=B6?= =?UTF-8?q?=E5=8E=9F=E5=87=BD=E6=95=B0=E4=BC=9A=E6=9C=89=E5=89=8D=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E7=9A=84=E5=85=B7=E4=BD=93=E5=8E=9F?= =?UTF-8?q?=E5=9B=A0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index cffdca2..d21d818 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -449,40 +449,51 @@ public static OrientationType IsClockWise(this IEnumerable pnts) return ca2d; } + /// + /// 叉积,二维叉乘计算 + /// + /// 原点 + /// oa向量 + /// ob向量,此为判断点 + /// 返回值有正负,表示绕原点四象限的位置变换,也就是有向面积 + 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 static List ConvexHull(this List points) + public static List? ConvexHull(this List points) { - if (points.Count <= 1) - return points; + if (points.Count < 3) return null; - int n = points.Count, k = 0; - List H = [..new Point2d[2 * n]]; + //坐标排序 + points = points.OrderBy(p => p.X).ThenBy(p => p.Y).ToList(); - points.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); + var hullPts = new List(); - // Build lower hull - for (var i = 0; i < n; ++i) - { - while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == - OrientationType.CounterClockWise) - k--; - H[k++] = points[i]; + //构建下凸包 + foreach (var pt in points) { + while (hullPts.Count >= 2 && Cross(hullPts[^2], hullPts[^1], pt) <= 0) + hullPts.RemoveAt(hullPts.Count - 1); + hullPts.Add(pt); } - // Build upper hull - for (int i = n - 2, t = k + 1; i >= 0; i--) - { - while (k >= t && IsClockWise(H[k - 2], H[k - 1], points[i]) == - OrientationType.CounterClockWise) - k--; - H[k++] = points[i]; + //构建上凸包 + var lowerHullCount = hullPts.Count + 1; + for (var i = points.Count - 2; i >= 0; i--) { + while (hullPts.Count >= lowerHullCount && Cross(hullPts[^2], hullPts[^1], points[i]) <= 0) + hullPts.RemoveAt(hullPts.Count - 1); + hullPts.Add(points[i]); } - return H.Take(k - 1).ToList(); + //移除与起点重复的尾点 + hullPts.RemoveAt(hullPts.Count - 1); + + return hullPts.Count >= 3 ? hullPts : null; } #endregion PointList -- Gitee