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; } = "";
}