diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs
index a9227a0ee85e20357d1c110e314dca5d8d8fb46a..39eb5d774f30196370747ee919b2b945431a8123 100644
--- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs
+++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs
@@ -2,217 +2,382 @@
namespace IFoxCAD.Cad;
///
-/// AABB和OBB信息
+/// 和尚777 重构
+/// 包围盒信息
///
public struct BoundingInfo
{
- public double MinX;
- public double MinY;
- public double MinZ;
-
- public double MaxX;
- public double MaxY;
- public double MaxZ;
-
- ///
- /// AABB这里永远是0
- ///
- public double Angle;
- public bool IsEffective;
-
- public Point3d Min => new(MinX, MinY, MinZ);
- public Point3d Max => new(MaxX, MaxY, MaxZ);
- public Extents3d Extents3d => new(Min, Max);
- public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY);
-
- public BoundingInfo(double minX, double minY, double minZ,
- double maxX, double maxY, double maxZ,
- bool isEffective, double angle = 0)
- {
- MinX = minX;
- MinY = minY;
- MinZ = minZ;
- MaxX = maxX;
- MaxY = maxY;
- MaxZ = maxZ;
- IsEffective = isEffective;
- Angle = angle;
- }
+ public double MinX;
+ public double MinY;
+ public double MinZ;
- public BoundingInfo(Point3d min, Point3d max, bool isEffective, double angle = 0)
- : this(min.X, min.Y, min.Z,
- max.X, max.Y, max.Z,
- isEffective, angle)
- { }
-
- // public BoundingInfo(Rect rect, double angle = 0)
- // {
- // MinX = rect.X;
- // MinY = rect.Y;
- // MinZ = 0;
- // MaxX = rect.Right;
- // MaxY = rect.Top;
- // MaxZ = 0;
- // Angle = angle;
- // }
-
- public override string ToString()
- {
- return Extents3d.ToString();
- }
+ public double MaxX;
+ public double MaxY;
+ public double MaxZ;
+
+ #region 包围盒9位码坐标
+ /*
+ * 包围盒9位码坐标
+ * P7---------------P8----------------P9
+ * | | |
+ * | | |
+ * | | |
+ * P4---------------P5----------------P6
+ * | | |
+ * | | |
+ * | | |
+ * P1---------------P2----------------P3
+ */
+ ///
+ /// 左下点 P1
+ ///
+ public Point3d BottomLeft => new(MinX, MinY, MinZ);
+ ///
+ /// P2
+ ///
+ public Point3d BottomCenter => BottomLeft.GetMidPointTo(BottomRight);
+ ///
+ /// P3
+ ///
+ public Point3d BottomRight => new(MaxX, MinY, MinZ);
+ ///
+ /// P4
+ ///
+ public Point3d MidLeft => BottomLeft.GetMidPointTo(TopLeft);
+ ///
+ /// P5
+ ///
+ public Point3d MidCenter => BottomLeft.GetMidPointTo(TopRight);
+ ///
+ /// P6
+ ///
+ public Point3d MidRight => BottomRight.GetMidPointTo(TopRight);
+ ///
+ /// P7
+ ///
+ public Point3d TopLeft => new(MinX, MaxY, MinZ);
+ ///
+ /// P8
+ ///
+ public Point3d TopCenter => TopLeft.GetMidPointTo(TopRight);
+ ///
+ /// 右上点 P9
+ ///
+ public Point3d TopRight => new(MaxX, MaxY, MaxZ);
+
+ // public Point3d Min => new(MinX, MinY, MinZ);
+
+ // public Point3d Max => new(MaxX, MaxY, MaxZ);
+ #endregion
+
+ public double Height => Math.Abs(MaxX - MinX);
+ public double Width => Math.Abs(MaxY - MinY);
+ public double Area => Height * Width;
+ public Extents3d Extents3d { get; }
+ public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY);
+
+ public BoundingInfo(Extents3d ext)
+ {
+ MinX = ext.MinPoint.X;
+ MinY = ext.MinPoint.Y;
+ MinZ = ext.MinPoint.Z;
+ MaxX = ext.MaxPoint.X;
+ MaxY = ext.MaxPoint.Y;
+ MaxZ = ext.MaxPoint.Z;
+ Extents3d = ext;
+ }
+ public BoundingInfo(Extents2d ext)
+ {
+ MinX = ext.MinPoint.X;
+ MinY = ext.MinPoint.Y;
+ MinZ = 0;
+ MaxX = ext.MaxPoint.X;
+ MaxY = ext.MaxPoint.Y;
+ MaxZ = 0;
+ var pt1 = new Point3d(MinX, MinY, 0);
+ var pt9 = new Point3d(MaxX, MaxY, 0);
+ Extents3d = new Extents3d(pt1, pt9);
+ }
+ public override string ToString()
+ {
+ return Extents3d.ToString();
+ }
+
+ public void Move(Point3d pt1, Point3d pt2)
+ {
+ var ve = pt1 - pt2;
+ MinX -= ve.X;
+ MinY -= ve.Y;
+ MinZ -= ve.Z;
+ MaxX -= ve.X;
+ MaxY -= ve.Y;
+ MaxZ -= ve.Z;
+ }
+
+}
+public static class EntityBoundingInfo
+{
+
+ ///
+ /// 获取包围盒信息
+ ///
+ ///
+ ///
+ ///
+ public static BoundingInfo? GetBoundingInfo(this Extents3d ext)
+ {
+ return new(ext);
+ }
+
+ // 包围盒外扩
+ //public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0)
+ //{
+ // var p1 = ext.MinPoint.Offset(-dist, -dist);
+ // var p2 = ext.MaxPoint.Offset(dist, dist);
+ // var e = new Extents3d(p1, p2);
+ // return new(e);
+ //}
+
+ ///
+ /// 获取实体包围盒
+ ///
+ ///
+ ///
+ static Extents3d? GetEntityBox(this Entity ent)
+ {
+ if (!ent.Bounds.HasValue)
+ return null;
+ //if (ent is BlockReference brf)
+ // ext = brf.GeometryExtentsBestFit();
- public void Move(Point3d pt1, Point3d pt2)
+ if (ent is Spline spl)
+ return spl.ToPolyline().GeometricExtents;
+
+ else if (ent is MText mtext)
+ return GetMTextBox(mtext);
+
+ else if (ent is Table table)
{
- var ve = pt1 - pt2;
- MinX -= ve.X;
- MinY -= ve.Y;
- MinZ -= ve.Z;
- MaxX -= ve.X;
- MaxY -= ve.Y;
- MaxZ -= ve.Z;
+ table.RecomputeTableBlock(true);
+ return table.GeometricExtents;
}
-}
-public class EntityBoundingInfo
-{
- #region 保存异常类型的日志
-
- static readonly HashSet _typeNames;
- ///
- /// 为了保证更好的性能,
- /// 只是在第一次调用此功能的时候进行读取,
- /// 免得高频调用时候高频触发磁盘
- ///
- static EntityBoundingInfo()
+ else if (ent is Dimension dim)
{
- _typeNames = new();
-
-
+ dim.RecomputeDimensionBlock(true);
+ return dim.GeometricExtents;
}
+ else
+ return ent.GeometricExtents;
-
+ }
-
- #endregion
+ ///
+ /// 获取多行文本的正交包围盒
+ ///
+ ///
+ ///
+ static Extents3d GetMTextBox(MText mText)
+ {
+ return mText.GetMTextBoxCorners().ToExtents3D();
+ }
- ///
- /// 获取图元包围盒
- ///
- ///
- /// (左下角,右上角,是否有效)
- /// 异常:
- /// 会将包围盒类型记录到所属路径中,以此查询
- public static BoundingInfo GetBoundingInfo(Entity ent)
+ ///
+ /// 获取点集包围盒
+ ///
+ ///
+ ///
+ static Extents3d ToExtents3D(this IEnumerable pts)
+ {
+ var ext = new Extents3d();
+ foreach (Point3d pt in pts)
{
-#if Debug_Cause_Error
- // 错误类型处理
- if (ent is AttributeDefinition) // 属性定义
- return new(Point3d.Origin, Point3d.Origin, false);
- if (ent is Xline xline)// 参照线
- return new(xline.BasePoint, xline.BasePoint, true);
- if (ent is Ray ray)// 射线
- return new(ray.BasePoint, ray.BasePoint, true);
-#endif
- // 指定类型处理
- if (ent is BlockReference brf)
- return GetBoxInfoInBlockReference(brf);
- if (ent is MText mText)
- return GetBoxInfoInMText(mText);
-
- if (!_typeNames.Contains(ent.GetType().Name)) // 屏蔽天正等等缺失包围盒的类型
- try
- {
- return new(ent.GeometricExtents.MinPoint, ent.GeometricExtents.MaxPoint, true);
- }
- catch { }
- return new(Point3d.Origin, Point3d.Origin, false);
+ ext.AddPoint(pt);
}
+ return ext;
+ }
- ///
- /// 处理块参照
- ///
- static BoundingInfo GetBoxInfoInBlockReference(BlockReference brf)
+ ///
+ /// 获取块的包围盒
+ ///
+ ///
+ ///
+ ///
+ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat)
+ {
+ if (en is BlockReference block)
{
- try
+ var matins = mat * block.BlockTransform;
+ if (block.BlockTableRecord.GetObject() is BlockTableRecord btr)
+ foreach (ObjectId id in btr)
{
- // 这个获取是原点附近,需要平移到块基点
- var fit = brf.GeometryExtentsBestFit();
- //var minX = fit.MinPoint.X + brf.Position.X;
- //var minY = fit.MinPoint.Y + brf.Position.Y;
- //var minZ = fit.MinPoint.Z + brf.Position.Z;
- //var maxX = fit.MaxPoint.X + brf.Position.X;
- //var maxY = fit.MaxPoint.Y + brf.Position.Y;
- //var maxZ = fit.MaxPoint.Z + brf.Position.Z;
- //return new(minX, minY, minZ, maxX, maxY, maxZ, true);
- return new(fit.MinPoint, fit.MaxPoint, true);
+ id.GetObject();
+ if (id.GetObject() is Entity ent1)
+ {
+ if (ent1.Visible != true)
+ continue;
+ if (ent1 is AttributeDefinition att)
+ {
+ if (att != null && (!att.Constant || att.Invisible))
+ continue;
+ }
+ GetBlockBox(ent1, ref ext, ref matins);
+ }
}
- catch
+ if (block.AttributeCollection.Count > 0)
+ {
+ foreach (ObjectId attid in block.AttributeCollection)
{
- // 如果是一条参照线的组块,将导致获取包围盒时报错
- // 0x01 是否需要进入块内,然后拿到每个图元的BasePoint再计算中点?感觉过于复杂.
- // 0x02 这个时候拿基点走就算了
- return new(brf.Position, brf.Position, true);
+ if (attid.GetObject() is AttributeReference att)
+ {
+ if (!att.Invisible && att.Visible)
+ GetBlockBox(att, ref ext, ref mat);
+ }
}
+ }
}
-
- ///
- /// 处理多行文字
- ///
- static BoundingInfo GetBoxInfoInMText(MText mtxt)
+ else
{
- /*
- * MText Aussehen
- * ------------------------------------
- * | | |
- * | | |ht
- * | | |
- * |-----wl-------插入点------wr-------|
- * | | |
- * | | |hb
- * | | |
- * ------------------------------------
- */
-
- double width = mtxt.ActualWidth;// 实际宽度
- double height = mtxt.ActualHeight;// 实际高度
- double wl = 0.0;
- double hb = 0.0;
-
- // 对齐方式
- switch (mtxt.Attachment)
+ if (mat.IsUniscaledOrtho())
+ {
+ using (var ent1 = en.GetTransformedCopy(mat))
{
- case AttachmentPoint.TopCenter:
- case AttachmentPoint.MiddleCenter:
- case AttachmentPoint.BottomCenter:
- wl = width * -0.5;
- break;
- case AttachmentPoint.TopRight:
- case AttachmentPoint.MiddleRight:
- case AttachmentPoint.BottomRight:
- wl = -width;
- break;
+ if (ext.IsEmptyExt())
+ {
+ var e = ent1.GetEntityBox();
+ if (e.HasValue)
+ ext = e.Value;
+ }
+ else
+ {
+ var e = ent1.GetEntityBox();
+ if (e.HasValue)
+ ext.AddExtents(e.Value);
+ }
}
- switch (mtxt.Attachment)
+ }
+ else
+ {
+ var e = en.GetEntityBox();
+ if (e.HasValue)
{
- case AttachmentPoint.TopLeft:
- case AttachmentPoint.TopCenter:
- case AttachmentPoint.TopRight:
- hb = -height;// 下边线到插入点的距离
- break;
- case AttachmentPoint.MiddleLeft:
- case AttachmentPoint.MiddleCenter:
- case AttachmentPoint.MiddleRight:
- hb = height * -0.5;
- break;
+ Extents3d entext = e.Value;
+ entext.TransformBy(mat);
+ if (ext.IsEmptyExt())
+ ext = entext;
+ else
+ ext.AddExtents(entext);
}
+ return;
+ }
+ }
+ return;
+ }
+ ///
+ /// 获取多行文字最小包围盒4点坐标
+ ///
+ ///
+ ///
+ public static Point3d[] GetMTextBoxCorners(this MText mtext)
+ {
+ double width = mtext.ActualWidth;
+ double height = mtext.ActualHeight;
+ Point3d point1, point2;
+ switch (mtext.Attachment)
+ {
+ case AttachmentPoint.TopLeft:
+ default:
+ point1 = new Point3d(0.0, -height, 0.0);
+ point2 = new Point3d(width, 0.0, 0.0);
+ break;
+ case AttachmentPoint.TopCenter:
+ point1 = new Point3d(-width * 0.5, -height, 0.0);
+ point2 = new Point3d(width * 0.5, 0.0, 0.0);
+ break;
+ case AttachmentPoint.TopRight:
+ point1 = new Point3d(-width, -height, 0.0);
+ point2 = new Point3d(0.0, 0.0, 0.0);
+ break;
+ case AttachmentPoint.MiddleLeft:
+ point1 = new Point3d(0.0, -height * 0.5, 0.0);
+ point2 = new Point3d(width, height * 0.5, 0.0);
+ break;
+ case AttachmentPoint.MiddleCenter:
+ point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0);
+ point2 = new Point3d(width * 0.5, height * 0.5, 0.0);
+ break;
+ case AttachmentPoint.MiddleRight:
+ point1 = new Point3d(-width, -height * 0.5, 0.0);
+ point2 = new Point3d(0.0, height * 0.5, 0.0);
+ break;
+ case AttachmentPoint.BottomLeft:
+ point1 = new Point3d(0.0, 0.0, 0.0);
+ point2 = new Point3d(width, height, 0.0);
+ break;
+ case AttachmentPoint.BottomCenter:
+ point1 = new Point3d(-width * 0.5, 0.0, 0.0);
+ point2 = new Point3d(width * 0.5, height, 0.0);
+ break;
+ case AttachmentPoint.BottomRight:
+ point1 = new Point3d(-width, 0.0, 0.0);
+ point2 = new Point3d(0.0, height, 0.0);
+ break;
+ }
- double wr = width + wl;
- double ht = height + hb;
+ var xform =
+ Matrix3d.Displacement(mtext.Location.GetAsVector()) *
+ Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) *
+ Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal));
- Point3d center = mtxt.Location;
- return new(center.X + wl, center.Y + hb, 0,
- center.X + wr, center.Y + ht, 0,
- true,
- mtxt.Rotation);
+ return new[]
+ {
+ point1.TransformBy(xform),
+ new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform),
+ point2.TransformBy(xform),
+ new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform)
+ };
+ }
+ ///
+ /// 获取实体包围盒
+ ///
+ ///
+ ///
+ public static Extents3d? GetEntityBoxEx( Entity ent)
+ {
+ if (ent is BlockReference block)
+ {
+ Extents3d blockExt = default;
+ var mat = Matrix3d.Identity;
+ block!.GetBlockBox(ref blockExt, ref mat);
+ if (blockExt.IsEmptyExt())
+ return null;
+ return blockExt;
}
+ return GetEntityBox(ent);
+ }
+
+ ///
+ /// 判断包围盒是否有效
+ ///
+ ///
+ ///
+ static bool IsEmptyExt(this Extents3d ext)
+ {
+ if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint)
+ return true;
+ else
+ return false;
+ }
+ ///
+ /// 点偏移
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ //static Point3d Offset(this Point3d pt, double x, double y, double z = 0)
+ //{
+ // return new Point3d(pt.X + x, pt.Y + y, pt.Z + z);
+ //}
}
\ No newline at end of file
diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs
index bd7c64d122c686e8c06029ec6581cee4868a1751..c3a283421301219d47197e6d25c289d3e3111731 100644
--- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs
+++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs
@@ -132,8 +132,9 @@ public static Extents3d GetExtents(this IEnumerable ents)
var ext = new Extents3d();
foreach (var item in ents)
{
- if (item.Bounds.HasValue)
- ext.AddExtents(item.GeometricExtents);
+ var e = item.GetBoundingBoxEx();
+ if (e.HasValue)
+ ext.AddExtents(e.Value.Extents3d);
}
return ext;
}
@@ -146,12 +147,11 @@ public static Extents3d GetExtents(this IEnumerable ents)
///
///
/// 包围盒信息
- /// 异常:
- /// 会将包围盒类型记录到所属路径中,以此查询
- public static BoundingInfo GetBoundingBoxEx(this Entity ent)
+ public static BoundingInfo? GetBoundingBoxEx(this Entity ent)
{
- return EntityBoundingInfo.GetBoundingInfo(ent);
+ return EntityBoundingInfo.GetEntityBoxEx(ent)?.GetBoundingInfo();
}
+
///
/// 获取拉伸点
///