feat(query): инструмент get_part_info (МЦХ детали)

QueryService через IMassInertiaParam7: объём, масса, площадь, центр масс.
Единицы выставляются детерминированно (мм/кг) через LengthUnits/MassUnits —
иначе КОМПАС отдаёт значения в единицах отображения МЦХ (по умолчанию см/г).
Calculate() возвращает FALSE даже при успехе → опираемся на свойство Actual.

Интеграционный тест: цилиндр R10×H20 → V≈6283 мм³, S≈1885 мм², m≈0.049 кг, Zc=10 мм.
Находка задокументирована в OPEN_QUESTIONS; презентация обновлена (19 инструментов, 14 тестов).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@
This commit is contained in:
2026-05-26 09:35:57 +03:00
parent 60cf26f739
commit b73748f84b
7 changed files with 172 additions and 5 deletions
@@ -0,0 +1,60 @@
using Kompas.Mcp.Core.Documents;
using Kompas.Mcp.Core.Modeling;
using Kompas.Mcp.Core.Query;
namespace Kompas.Mcp.Tests.Integration;
/// <summary>Интеграция: массово-центровочные характеристики (get_part_info).</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class QueryTests
{
private readonly DocumentService _docs;
private readonly PartModeler _modeler;
private readonly QueryService _query;
public QueryTests(KompasFixture fx)
{
_docs = new DocumentService(fx.Session, fx.Dispatcher);
_modeler = new PartModeler(fx.Session, fx.Dispatcher);
_query = new QueryService(fx.Session, fx.Dispatcher);
}
[Fact]
public async Task Cylinder_volume_matches_formula()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
// Цилиндр R10 × H20 на XOY: объём = π·R²·H = π·100·20 ≈ 6283.19 мм³.
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
await _modeler.AddCircleAsync(s, 0, 0, 10);
await _modeler.CloseSketchAsync(s);
var boss = await _modeler.ExtrudeAsync(s, depth: 20);
Assert.True(boss > 0);
await _modeler.RebuildAsync();
var info = await _query.GetPartInfoAsync();
// Единицы детерминированы сервисом: мм³, мм², кг, мм.
var expectedVolume = Math.PI * 100 * 20; // ≈ 6283.19 мм³
Assert.InRange(info.Volume, expectedVolume * 0.99, expectedVolume * 1.01);
// Центр масс цилиндра — на оси, по высоте посередине (Z = H/2 = 10 мм).
Assert.InRange(info.CenterX, -0.1, 0.1);
Assert.InRange(info.CenterY, -0.1, 0.1);
Assert.InRange(info.CenterZ, 9.9, 10.1);
// Площадь поверхности: 2·π·R² (торцы) + 2·π·R·H (бок) = 2π·100 + 2π·10·20 ≈ 1884.96 мм².
var expectedArea = 2 * Math.PI * 100 + 2 * Math.PI * 10 * 20;
Assert.InRange(info.Area, expectedArea * 0.98, expectedArea * 1.02);
// Масса стального цилиндра (плотность ≈ 7.856 г/см³): V[см³]·ρ ≈ 6.283·7.856 ≈ 49.36 г = 0.0494 кг.
Assert.InRange(info.Mass, 0.045, 0.055);
}
finally
{
await _docs.CloseAsync(save: false);
}
}
}