@
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:
@@ -0,0 +1,61 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using Kompas.Mcp.Core.Threading;
|
||||
using Kompas6Constants;
|
||||
using KompasAPI7;
|
||||
|
||||
namespace Kompas.Mcp.Core.Query;
|
||||
|
||||
/// <summary>Запросы к активной 3D-модели: массово-центровочные характеристики.</summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
public sealed class QueryService
|
||||
{
|
||||
private readonly KompasSession _session;
|
||||
private readonly KompasDispatcher _dispatcher;
|
||||
|
||||
public QueryService(KompasSession session, KompasDispatcher dispatcher)
|
||||
{
|
||||
_session = session ?? throw new ArgumentNullException(nameof(session));
|
||||
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
/// <summary>Рассчитать и вернуть МЦХ активной детали (объём, масса, площадь, центр масс).</summary>
|
||||
public Task<PartInfo> GetPartInfoAsync(CancellationToken ct = default)
|
||||
=> _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var doc3d = _session.Application.ActiveDocument as IKompasDocument3D
|
||||
?? throw new InvalidOperationException("Активный документ не является 3D-моделью.");
|
||||
var part = doc3d.TopPart
|
||||
?? throw new InvalidOperationException("Не удалось получить вершинный компонент.");
|
||||
try
|
||||
{
|
||||
var mass = (IMassInertiaParam7)part;
|
||||
|
||||
// Детерминированные единицы: длина — мм, масса — кг. Иначе КОМПАС вернёт
|
||||
// значения в единицах отображения МЦХ (по умолчанию см/г), что зависит от настроек.
|
||||
mass.LengthUnits = ksLengthUnitsEnum.ksLUnMM;
|
||||
mass.MassUnits = ksMassUnitsEnum.ksMUnKG;
|
||||
|
||||
// Calculate() возвращает FALSE и при успехе (когда расчёт уже актуален),
|
||||
// поэтому ориентируемся на свойство Actual, а не на возвращаемое значение.
|
||||
mass.Calculate();
|
||||
if (!mass.Actual)
|
||||
throw new InvalidOperationException("МЦХ не рассчитаны (модель пуста или не перестроена?).");
|
||||
|
||||
return new PartInfo
|
||||
{
|
||||
Volume = mass.Volume,
|
||||
Mass = mass.Mass,
|
||||
Area = mass.Area,
|
||||
CenterX = mass.Xc,
|
||||
CenterY = mass.Yc,
|
||||
CenterZ = mass.Zc,
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
// part и его QI-приведение mass — один RCW; release один раз.
|
||||
if (Marshal.IsComObject(part)) Marshal.ReleaseComObject(part);
|
||||
}
|
||||
}, ct);
|
||||
}
|
||||
Reference in New Issue
Block a user