using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.BoundaryRepresentation; using BrepFace = Autodesk.AutoCAD.BoundaryRepresentation.Face; namespace FurnitureExporter; /// /// 倒角检测器 - 从板材实体中提取倒角/圆角信息 /// public class ChamferDetector { private readonly Database _db; private Point3d _originOffset = Point3d.Origin; // 检测参数 private const double MIN_CHAMFER_SIZE = 0.5; // 最小倒角尺寸 0.5mm private const double MAX_CHAMFER_SIZE = 50; // 最大倒角尺寸 50mm private const double MIN_FILLET_RADIUS = 1; // 最小圆角半径 1mm private const double MAX_FILLET_RADIUS = 100; // 最大圆角半径 100mm public ChamferDetector(Database db) { _db = db; } /// /// 从板材实体中检测倒角和圆角 /// public List DetectEdgeFeatures(ObjectId solidId, string panelId, Point3d? originOffset = null) { _originOffset = originOffset ?? Point3d.Origin; var features = new List(); using var tr = _db.TransactionManager.StartTransaction(); var solid = tr.GetObject(solidId, OpenMode.ForRead) as Solid3d; if (solid == null) { tr.Commit(); return features; } try { using var brep = new Brep(solid); int featureIndex = 0; // 遍历所有面,检测圆柱面(圆角)和平面相交的特殊边 foreach (var face in brep.Faces) { try { // face.Surface 常常是修剪/偏移表面,先剥离到基础几何类型 var surface = BrepSurfaceUtils.Unwrap(face.Surface); // 检测圆角(圆柱面) if (surface is Cylinder cylinder) { var radius = cylinder.Radius; // 过滤:圆角的半径通常较小,而孔的半径通常大于5mm if (radius >= MIN_FILLET_RADIUS && radius <= MAX_FILLET_RADIUS) { // 判断是圆角还是孔 if (IsFilletFace(face, cylinder, solid)) { var feature = ExtractFilletInfo(cylinder, face, panelId, featureIndex++); if (feature != null) { features.Add(feature); } } } } // 检测倒角(倾斜平面) else if (surface is Plane plane) { if (IsChamferFace(face, plane, solid)) { var feature = ExtractChamferInfo(plane, face, panelId, featureIndex++); if (feature != null) { features.Add(feature); } } } } catch { continue; } } } catch (System.Exception ex) { System.Diagnostics.Debug.WriteLine($"[ChamferDetector] Error: {ex.Message}"); } tr.Commit(); return features; } /// /// 判断圆柱面是否为圆角(而非孔的侧面) /// private bool IsFilletFace(BrepFace face, Cylinder cylinder, Solid3d solid) { try { // 获取圆柱半径 var radius = cylinder.Radius; // 获取实体尺寸 var solidExt = solid.GeometricExtents; var solidSize = solidExt.MaxPoint - solidExt.MinPoint; var maxSolidDim = Math.Max(solidSize.X, Math.Max(solidSize.Y, solidSize.Z)); // 圆角特征:半径较小(相对于实体尺寸) var radiusRatio = radius / maxSolidDim; // 如果半径小于实体最大尺寸的10%,很可能是圆角 if (radiusRatio < 0.1) { return true; } return false; } catch { return false; } } /// /// 判断平面是否为倒角面 /// private bool IsChamferFace(BrepFace face, Plane plane, Solid3d solid) { try { // 获取平面法向量 var normal = plane.Normal.GetNormal(); // 倒角面的法向量不会与主轴完全平行 var absNormal = new Vector3d(Math.Abs(normal.X), Math.Abs(normal.Y), Math.Abs(normal.Z)); // 如果法向量与任意主轴的夹角在25°-65°之间,可能是倒角 var maxComponent = Math.Max(absNormal.X, Math.Max(absNormal.Y, absNormal.Z)); var minComponent = Math.Min(absNormal.X, Math.Min(absNormal.Y, absNormal.Z)); // 倒角面的法向量不会太接近主轴(>0.9)也不会太远离(<0.4) if (maxComponent > 0.4 && maxComponent < 0.9 && minComponent > 0.1) { return true; } return false; } catch { return false; } } /// /// 提取圆角信息 /// private EdgeFeatureInfo? ExtractFilletInfo(Cylinder cylinder, BrepFace face, string panelId, int index) { try { // 使用圆柱原点作为圆角位置 var origin = cylinder.Origin; var center = new Point3d( origin.X + _originOffset.X, origin.Y + _originOffset.Y, origin.Z + _originOffset.Z ); var axis = cylinder.AxisOfSymmetry.GetNormal(); return new EdgeFeatureInfo { Id = $"{panelId}_fillet_{index:D3}", Type = "fillet", Position = new double[] { Math.Round(center.X, 2), Math.Round(center.Y, 2), Math.Round(center.Z, 2) }, Direction = new double[] { Math.Round(axis.X, 4), Math.Round(axis.Y, 4), Math.Round(axis.Z, 4) }, Radius = Math.Round(cylinder.Radius, 2), Length = 0, // 长度无法准确获取 PanelId = panelId }; } catch { return null; } } /// /// 提取倒角信息 /// private EdgeFeatureInfo? ExtractChamferInfo(Plane plane, BrepFace face, string panelId, int index) { try { // 使用平面原点作为倒角位置 var origin = plane.PointOnPlane; var center = new Point3d( origin.X + _originOffset.X, origin.Y + _originOffset.Y, origin.Z + _originOffset.Z ); var normal = plane.Normal.GetNormal(); return new EdgeFeatureInfo { Id = $"{panelId}_chamfer_{index:D3}", Type = "chamfer", Position = new double[] { Math.Round(center.X, 2), Math.Round(center.Y, 2), Math.Round(center.Z, 2) }, Direction = new double[] { Math.Round(normal.X, 4), Math.Round(normal.Y, 4), Math.Round(normal.Z, 4) }, Size = 0, // 倒角尺寸(无法准确获取) Length = 0, PanelId = panelId }; } catch { return null; } } } /// /// 边缘特征信息(倒角/圆角) /// public class EdgeFeatureInfo { /// /// 特征 ID /// public string Id { get; set; } = ""; /// /// 特征类型: "fillet"(圆角)| "chamfer"(倒角) /// public string Type { get; set; } = ""; /// /// 特征中心位置 [X, Y, Z] (mm) /// public double[] Position { get; set; } = new double[3]; /// /// 特征方向/法向量 [X, Y, Z] /// public double[] Direction { get; set; } = new double[3]; /// /// 圆角半径 (mm),仅用于 fillet 类型 /// public double? Radius { get; set; } /// /// 倒角尺寸 (mm),仅用于 chamfer 类型 /// public double? Size { get; set; } /// /// 特征长度 (mm) /// public double Length { get; set; } /// /// 所属板材 ID /// public string PanelId { get; set; } = ""; }