From 36114f798158c57564145bd69c504a28226ef320 Mon Sep 17 00:00:00 2001 From: SeWZC <36623158+SeWZC@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:39:31 +0800 Subject: [PATCH] =?UTF-8?q?BoundingBox2d=20=E4=B8=AD=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=B8=8E=E5=B7=A6=E5=8F=B3=E3=80=81=E4=B8=8A=E4=B8=8B=E6=9C=89?= =?UTF-8?q?=E5=85=B3=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E4=BB=A5=E4=B8=AD=E5=BF=83=E7=82=B9=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E4=B8=BA=E5=9F=BA=E7=A1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BoundingBox2D.cs | 115 ++++++++++++------ DotNetCampus.Numerics.Geometry/Size2D.cs | 29 ++++- 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/DotNetCampus.Numerics.Geometry/BoundingBox2D.cs b/DotNetCampus.Numerics.Geometry/BoundingBox2D.cs index c204b34..d49e101 100644 --- a/DotNetCampus.Numerics.Geometry/BoundingBox2D.cs +++ b/DotNetCampus.Numerics.Geometry/BoundingBox2D.cs @@ -16,6 +16,13 @@ public readonly record struct BoundingBox2D #region 静态方法 + private static BoundingBox2D CreateInternal(double minX, double minY, double maxX, double maxY) + { + return new BoundingBox2D( + new Point2D((minX + maxX) / 2, (minY + maxY) / 2), + new Size2D((maxX - minX) / 2, (maxY - minY) / 2)); + } + /// /// 创建一个 2 维边界框。 /// @@ -31,18 +38,40 @@ public static BoundingBox2D Create(double minX, double minY, double maxX, double throw new ArgumentException("The minimum value of the bounding box must be less than or equal to the maximum value."); } - return new BoundingBox2D(minX, minY, maxX, maxY); + return CreateInternal(minX, minY, maxX, maxY); } /// - /// 通过左上角位置和大小创建 2 维边界框。 + /// 通过最小坐标位置和大小创建 2 维边界框。 /// - /// 左上角位置。 + /// 最小坐标位置。 /// 大小。 /// 创建的 2 维边界框。 - public static BoundingBox2D CreateByLocationSize(Point2D location, Size2D size) + public static BoundingBox2D CreateByMinPointSize(Point2D minPoint, Size2D size) { - return Create(location.X, location.Y, location.X + size.Width, location.Y + size.Height); + if (size.Width < 0 || size.Height < 0) + { + throw new ArgumentException("The size of the bounding box cannot be negative."); + } + + var halfSize = size / 2; + return new BoundingBox2D(minPoint + new Vector2D(halfSize.Width, halfSize.Height), halfSize); + } + + /// + /// 通过中心点和大小创建 2 维边界框。 + /// + /// + /// + /// + public static BoundingBox2D CreateByCenterSize(Point2D center, Size2D size) + { + if (size.Width < 0 || size.Height < 0) + { + throw new ArgumentException("The size of the bounding box cannot be negative."); + } + + return new BoundingBox2D(center, size / 2); } /// @@ -52,7 +81,7 @@ public static BoundingBox2D CreateByLocationSize(Point2D location, Size2D size) /// 宽高为 0 但不为空的 2 维边界框。 public static BoundingBox2D Create(Point2D point) { - return new BoundingBox2D(point.X, point.Y, point.X, point.Y); + return new BoundingBox2D(point, new Size2D()); } /// @@ -63,7 +92,7 @@ public static BoundingBox2D Create(Point2D point) /// 包含两个点的最小 2 维边界框。 public static BoundingBox2D Create(Point2D point1, Point2D point2) { - return new BoundingBox2D( + return CreateInternal( Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y), Math.Max(point1.X, point2.X), @@ -95,7 +124,7 @@ public static BoundingBox2D Create(IReadOnlyCollection points) maxY = Math.Max(maxY, point.Y); } - return new BoundingBox2D(minX, minY, maxX, maxY); + return CreateInternal(minX, minY, maxX, maxY); } /// @@ -113,7 +142,7 @@ public static BoundingBox2D TryCreate(double minX, double minY, double maxX, dou return Empty; } - return new BoundingBox2D(minX, minY, maxX, maxY); + return CreateInternal(minX, minY, maxX, maxY); } #endregion @@ -130,39 +159,64 @@ public static BoundingBox2D TryCreate(double minX, double minY, double maxX, dou #region 属性 /// - /// 最小 X 值。 + /// 中心点。 /// - public double MinX { get; } + public Point2D Center { get; } /// - /// 最小 Y 值。 + /// 边界框的大小的一半。 /// - public double MinY { get; } + public Size2D HalfSize { get; } /// - /// 最大 X 值。 + /// 半宽度。 /// - public double MaxX { get; } + public double HalfWidth => HalfSize.Width; /// - /// 最大 Y 值。 + /// 半高度。 /// - public double MaxY { get; } + public double HalfHeight => HalfSize.Height; /// - /// 边界框是否为空。宽高为 0 的边界框不一定为空。 + /// 边界框的大小。 /// - public bool IsEmpty => !_isNotEmpty; + public Size2D Size => new(Width, Height); /// /// 宽度。 /// - public double Width => MaxX - MinX; + public double Width => HalfWidth * 2; /// /// 高度。 /// - public double Height => MaxY - MinY; + public double Height => HalfHeight * 2; + + /// + /// 最小 X 值。 + /// + public double MinX => Math.Min(Center.X - HalfWidth, Center.X + HalfWidth); + + /// + /// 最小 Y 值。 + /// + public double MinY => Math.Min(Center.Y - HalfHeight, Center.Y + HalfHeight); + + /// + /// 最大 X 值。 + /// + public double MaxX => Math.Max(Center.X - HalfWidth, Center.X + HalfWidth); + + /// + /// 最大 Y 值。 + /// + public double MaxY => Math.Max(Center.Y - HalfHeight, Center.Y + HalfHeight); + + /// + /// 边界框是否为空。宽高为 0 的边界框不一定为空。 + /// + public bool IsEmpty => !_isNotEmpty; /// /// 边界框坐标值最小的点(MinX, MinY)。 @@ -174,11 +228,6 @@ public static BoundingBox2D TryCreate(double minX, double minY, double maxX, dou /// public Point2D MaxPoint => new(MaxX, MaxY); - /// - /// 中心点。 - /// - public Point2D Center => new((MinX + MaxX) / 2, (MinY + MaxY) / 2); - #endregion #region 构造函数 @@ -188,21 +237,13 @@ public static BoundingBox2D TryCreate(double minX, double minY, double maxX, dou /// public BoundingBox2D() { - MinX = 0; - MinY = 0; - MaxX = 0; - MaxY = 0; - _isNotEmpty = false; } - private BoundingBox2D(double minX, double minY, double maxX, double maxY) + private BoundingBox2D(Point2D center, Size2D halfSize) { - MinX = minX; - MinY = minY; - MaxX = maxX; - MaxY = maxY; - + Center = center; + HalfSize = halfSize; _isNotEmpty = true; } diff --git a/DotNetCampus.Numerics.Geometry/Size2D.cs b/DotNetCampus.Numerics.Geometry/Size2D.cs index 5f37a8c..a0837a4 100644 --- a/DotNetCampus.Numerics.Geometry/Size2D.cs +++ b/DotNetCampus.Numerics.Geometry/Size2D.cs @@ -5,4 +5,31 @@ namespace DotNetCampus.Numerics.Geometry; /// /// 宽度。 /// 高度。 -public readonly record struct Size2D(double Width, double Height); +public readonly record struct Size2D(double Width, double Height) +{ + #region 运算符重载 + + /// + /// 将大小按指定倍数进行缩放。 + /// + /// + /// 缩放倍数。大于 1 为放大,小于 1 为缩小。 + /// + public static Size2D operator *(Size2D size, double scalar) + { + return new Size2D(size.Width * scalar, size.Height * scalar); + } + + /// + /// 将大小按指定倍数进行反向缩放。 + /// + /// + /// 反向缩放倍数。大于 1 为缩小,小于 1 为放大。 + /// + public static Size2D operator /(Size2D size, double scalar) + { + return new Size2D(size.Width / scalar, size.Height / scalar); + } + + #endregion +}