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:
2026-05-27 11:59:15 +03:00
parent 9079bec375
commit aec2f1e52f
4 changed files with 178 additions and 3 deletions
@@ -96,4 +96,55 @@ public sealed class HoleTests
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Counterbore_removes_base_plus_spotface()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
await _modeler.AddRectangleAsync(s, -20, -20, 20, 20);
await _modeler.CloseSketchAsync(s);
await _modeler.ExtrudeAsync(s, depth: 20);
var before = (await _query.GetPartInfoAsync()).Volume;
// Ø10 сквозное + цековка Ø20×5 по центру верхней грани.
await _holes.CounterboreHoleAsync(0, 0, 20, diameter: 10, depth: 0, throughAll: true,
spotDiameter: 20, spotDepth: 5);
var removed = before - (await _query.GetPartInfoAsync()).Volume;
// База: π·25·20 ≈ 1570.8; + кольцо цековки (π·100−π·25)·5 ≈ 1178 → итого ≈ 2749.
var baseCyl = Math.PI * 25 * 20;
var expected = Math.PI * 25 * 20 + Math.PI * (100 - 25) * 5;
Assert.True(removed > baseCyl * 1.1, "Цековка должна удалить больше, чем простое отверстие.");
Assert.InRange(removed, expected * 0.9, expected * 1.1);
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Countersink_removes_base_plus_cone()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
await _modeler.AddRectangleAsync(s, -20, -20, 20, 20);
await _modeler.CloseSketchAsync(s);
await _modeler.ExtrudeAsync(s, depth: 20);
var before = (await _query.GetPartInfoAsync()).Volume;
// Ø8 сквозное + зенковка Ø16 под 90° по центру верхней грани.
await _holes.CountersinkHoleAsync(0, 0, 20, diameter: 8, depth: 0, throughAll: true,
sinkDiameter: 16, sinkAngle: 90);
var removed = before - (await _query.GetPartInfoAsync()).Volume;
// База Ø8 сквозь 20 ≈ 1005; зенковка-конус добавляет ~270 (точное зависит от трактовки угла).
var baseCyl = Math.PI * 16 * 20;
Assert.True(removed > baseCyl, "Зенковка должна удалить больше, чем простое отверстие Ø8.");
Assert.True(removed < baseCyl * 2, "Объём зенковки в разумных пределах.");
}
finally { await _docs.CloseAsync(save: false); }
}
}