feat: типы отверстий — цековка и зенковка (hole_counterbore, hole_countersink) через API7
- HoleCore отрефакторен: параметр holeType + Action<IHole3D> configure (настройка HoleParameters) - CounterboreHoleAsync (ksHTCounterbore + ISpotfacingHoleParameters: SpotfacingDiameter/Depth) - CountersinkHoleAsync (ksHTCountersinking + ICountersinkHoleParameters: ksCTDiameterAngle, Diameter/Angle) - переиспользуется размещение/подбор направления/откат из базового hole - инструменты hole_counterbore, hole_countersink; интеграционные тесты (объём ±10% / больше базы) - 69 инструментов, 118 тестов; спек docs/superpowers/specs/2026-05-27-hole-types-design.md
This commit is contained in:
@@ -28,9 +28,49 @@ public sealed class HoleService
|
||||
/// diameter — диаметр (мм). throughAll — сквозное (depth игнорируется), иначе на глубину depth (мм).
|
||||
/// </summary>
|
||||
public Task HoleAsync(double x, double y, double z, double diameter, double depth, bool throughAll, CancellationToken ct = default)
|
||||
=> _dispatcher.InvokeAsync(() => HoleCore(x, y, z, diameter, depth, throughAll), ct);
|
||||
=> _dispatcher.InvokeAsync(() => HoleCore(x, y, z, diameter, depth, throughAll, ksHoleTypeEnum.ksHTBase, null), ct);
|
||||
|
||||
private void HoleCore(double x, double y, double z, double diameter, double depth, bool throughAll)
|
||||
/// <summary>Отверстие с цековкой (цилиндрическим уширением сверху, под винт с цилиндрической
|
||||
/// головкой): основное отверстие diameter + цековка spotDiameter×spotDepth.</summary>
|
||||
public Task CounterboreHoleAsync(double x, double y, double z, double diameter, double depth, bool throughAll,
|
||||
double spotDiameter, double spotDepth, CancellationToken ct = default)
|
||||
=> _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (!double.IsFinite(spotDiameter) || spotDiameter <= diameter)
|
||||
throw new ArgumentOutOfRangeException(nameof(spotDiameter), "Диаметр цековки должен быть больше диаметра отверстия.");
|
||||
if (!double.IsFinite(spotDepth) || spotDepth <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(spotDepth), "Глубина цековки должна быть > 0.");
|
||||
HoleCore(x, y, z, diameter, depth, throughAll, ksHoleTypeEnum.ksHTCounterbore, hole =>
|
||||
{
|
||||
var p = hole.HoleParameters as ISpotfacingHoleParameters
|
||||
?? throw new InvalidOperationException("HoleParameters не приводится к ISpotfacingHoleParameters.");
|
||||
p.SpotfacingDiameter = spotDiameter;
|
||||
p.SpotfacingDepth = spotDepth;
|
||||
});
|
||||
}, ct);
|
||||
|
||||
/// <summary>Отверстие с зенковкой (коническим уширением сверху, под винт с потайной головкой):
|
||||
/// основное отверстие diameter + зенковка sinkDiameter под углом sinkAngle (градусы, конус).</summary>
|
||||
public Task CountersinkHoleAsync(double x, double y, double z, double diameter, double depth, bool throughAll,
|
||||
double sinkDiameter, double sinkAngle, CancellationToken ct = default)
|
||||
=> _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (!double.IsFinite(sinkDiameter) || sinkDiameter <= diameter)
|
||||
throw new ArgumentOutOfRangeException(nameof(sinkDiameter), "Диаметр зенковки должен быть больше диаметра отверстия.");
|
||||
if (!double.IsFinite(sinkAngle) || sinkAngle <= 0 || sinkAngle >= 180)
|
||||
throw new ArgumentOutOfRangeException(nameof(sinkAngle), "Угол зенковки должен быть в (0; 180) градусов.");
|
||||
HoleCore(x, y, z, diameter, depth, throughAll, ksHoleTypeEnum.ksHTCountersinking, hole =>
|
||||
{
|
||||
var p = hole.HoleParameters as ICountersinkHoleParameters
|
||||
?? throw new InvalidOperationException("HoleParameters не приводится к ICountersinkHoleParameters.");
|
||||
p.CountersinkType = ksCountersinkTypeEnum.ksCTDiameterAngle; // задаём диаметр + угол
|
||||
p.CountersinkDiameter = sinkDiameter;
|
||||
p.CountersinkAngle = sinkAngle;
|
||||
});
|
||||
}, ct);
|
||||
|
||||
private void HoleCore(double x, double y, double z, double diameter, double depth, bool throughAll,
|
||||
ksHoleTypeEnum holeType, Action<IHole3D>? configure)
|
||||
{
|
||||
if (!double.IsFinite(x) || !double.IsFinite(y) || !double.IsFinite(z))
|
||||
throw new ArgumentException("Координаты точки отверстия должны быть конечными числами.");
|
||||
@@ -68,13 +108,14 @@ public sealed class HoleService
|
||||
{
|
||||
hole = container.Holes3D.Add()
|
||||
?? throw new InvalidOperationException("Holes3D.Add() вернул null.");
|
||||
hole.HoleType = ksHoleTypeEnum.ksHTBase;
|
||||
hole.HoleType = holeType;
|
||||
hole.Diameter = diameter;
|
||||
hole.DepthType = throughAll ? ksDepthTypeEnum.ksDTReachThrough : ksDepthTypeEnum.ksDTValue;
|
||||
if (!throughAll) hole.Depth = depth;
|
||||
hole.EndFaceType = ksEndFaceTypeEnum.ksEFFlat;
|
||||
hole.Axis = false;
|
||||
hole.ShowThread = false;
|
||||
configure?.Invoke(hole); // параметры цековки/зенковки (после установки HoleType)
|
||||
|
||||
var disp = (IHoleDisposal)hole;
|
||||
disp.BaseSurface = (IModelObject)face;
|
||||
|
||||
Reference in New Issue
Block a user