31b933e1cc
ksConvertTextToCurve ВОЗВРАЩАЕТ ссылку на кривые, и только по ней ksGetObjGabaritRect даёт габарит букв: по текстовой ссылке это ячейка строки (Arial h=10 «HH» — 23.75 против 19.97 у глифов, второе совпадает с выдавленным телом). Агент вписывает надпись в поле по габариту, поэтому в ответе теперь оба числа. OutputPath.Prepare создаёт каталог назначения и делает путь абсолютным (document_save, export_step, снимок): КОМПАС в несуществующую папку молча не пишет, а диагностика при этом винила занятое имя файла — чинили не ту причину. Причины разведены.
137 lines
6.9 KiB
C#
137 lines
6.9 KiB
C#
using System.Runtime.Versioning;
|
|
using Kompas.Mcp.Core.Documents;
|
|
using Kompas.Mcp.Core.Interop;
|
|
using Kompas.Mcp.Core.Threading;
|
|
using Kompas6Constants;
|
|
using KompasAPI7;
|
|
|
|
namespace Kompas.Mcp.Core.Conversion;
|
|
|
|
/// <summary>
|
|
/// Импорт/экспорт обменных форматов (STEP) через КОМПАС-конвертер.
|
|
/// <para>
|
|
/// Встроенный конвертер получается через <c>IApplication.get_Converter(код_формата)</c>
|
|
/// (целочисленный код <c>ksKOMPASConverterEnum</c>, НЕ путь к DLL), параметры — через
|
|
/// <c>IConverter.ConverterParameters</c>, сама конвертация — через
|
|
/// <c>IKompasDocument3D1.ConvertTo/FromAdditionFormat</c>.
|
|
/// </para>
|
|
/// </summary>
|
|
[SupportedOSPlatform("windows")]
|
|
public sealed class ConversionService
|
|
{
|
|
private readonly KompasSession _session;
|
|
private readonly KompasDispatcher _dispatcher;
|
|
|
|
public ConversionService(KompasSession session, KompasDispatcher dispatcher)
|
|
{
|
|
_session = session ?? throw new ArgumentNullException(nameof(session));
|
|
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Импортировать STEP-файл в новый документ заданного типа (по умолчанию — сборка) и сделать его активным.
|
|
/// <paramref name="createComponentFiles"/> — писать ли компоненты сборки отдельными .m3d рядом с STEP.
|
|
/// </summary>
|
|
public Task ImportStepAsync(
|
|
string path,
|
|
KompasDocumentType docType = KompasDocumentType.Assembly,
|
|
bool createComponentFiles = false,
|
|
CancellationToken ct = default)
|
|
=> _dispatcher.InvokeAsync(() => ImportCore(path, docType, createComponentFiles), ct);
|
|
|
|
private void ImportCore(string path, KompasDocumentType docType, bool createComponentFiles)
|
|
{
|
|
if (!File.Exists(path))
|
|
throw new FileNotFoundException($"STEP-файл не найден: {path}", path);
|
|
|
|
var app = _session.Application;
|
|
var typeEnum = DocumentTypes.ToEnum(docType);
|
|
IConverter? conv = null;
|
|
IAdditionConvertParameters? prm = null;
|
|
object? doc = null;
|
|
try
|
|
{
|
|
conv = GetConverter(app, StepFormats.ImportConverterCode); // -3
|
|
conv.GetFilter((int)typeEnum, false /* импорт */, out int cmd);
|
|
|
|
doc = app.Documents.Add(typeEnum, true);
|
|
if (doc is not IKompasDocument3D1 doc3d1)
|
|
throw new InvalidOperationException("Созданный документ не является 3D-документом (нет IKompasDocument3D1).");
|
|
|
|
prm = conv.ConverterParameters(cmd) as IAdditionConvertParameters
|
|
?? throw new InvalidOperationException("ConverterParameters вернул не IAdditionConvertParameters.");
|
|
prm.Format = (ksKOMPASConverterEnum)StepFormats.ImportConverterCode;
|
|
if (createComponentFiles)
|
|
{
|
|
// NeedCreateComponentsFiles может отсутствовать в Home-редакции КОМПАС —
|
|
// ловим COM-исключения; не критично, если свойство недоступно.
|
|
try { prm.NeedCreateComponentsFiles = true; }
|
|
catch (System.Runtime.InteropServices.COMException) { }
|
|
catch (System.Runtime.InteropServices.InvalidComObjectException) { }
|
|
catch (NotImplementedException) { }
|
|
}
|
|
|
|
if (!doc3d1.ConvertFromAdditionFormat(path, (AdditionConvertParameters)prm))
|
|
throw new InvalidOperationException("ConvertFromAdditionFormat вернул FALSE (импорт STEP не удался).");
|
|
}
|
|
finally
|
|
{
|
|
ComHelper.Release(prm);
|
|
ComHelper.Release(doc);
|
|
ComHelper.Release(conv);
|
|
}
|
|
}
|
|
|
|
/// <summary>Экспортировать активный 3D-документ в STEP по указанному пути.</summary>
|
|
public Task ExportStepAsync(string path, StepFormat format = StepFormat.Auto, CancellationToken ct = default)
|
|
=> _dispatcher.InvokeAsync(() => ExportCore(path, format), ct);
|
|
|
|
private void ExportCore(string path, StepFormat format)
|
|
{
|
|
// Каталог создаём сами: конвертер в несуществующую папку возвращает FALSE без причины.
|
|
var full = Documents.OutputPath.Prepare(path);
|
|
|
|
var app = _session.Application;
|
|
object? active = null;
|
|
IConverter? conv = null;
|
|
IAdditionConvertParameters? prm = null;
|
|
try
|
|
{
|
|
active = app.ActiveDocument
|
|
?? throw new InvalidOperationException("Нет активного документа для экспорта.");
|
|
if (active is not IKompasDocument3D1 doc3d1)
|
|
throw new InvalidOperationException("Активный документ не является 3D-документом (нет IKompasDocument3D1).");
|
|
|
|
int formatCode = StepFormats.ExportConverterCode(format);
|
|
conv = GetConverter(app, formatCode);
|
|
conv.GetFilter((int)DocumentTypeEnum.ksDocumentPart, true /* saveAs = экспорт */, out int cmd);
|
|
|
|
prm = conv.ConverterParameters(cmd) as IAdditionConvertParameters
|
|
?? throw new InvalidOperationException("ConverterParameters вернул не IAdditionConvertParameters.");
|
|
prm.Format = (ksKOMPASConverterEnum)formatCode;
|
|
|
|
if (!doc3d1.ConvertToAdditionFormat(full, (AdditionConvertParameters)prm))
|
|
throw new InvalidOperationException($"ConvertToAdditionFormat вернул FALSE (экспорт STEP по пути «{full}» не удался).");
|
|
}
|
|
finally
|
|
{
|
|
ComHelper.Release(prm);
|
|
ComHelper.Release(active);
|
|
ComHelper.Release(conv);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Получить встроенный конвертер. Для STEP get_Converter принимает целочисленный код формата
|
|
/// (boxed int), НЕ путь к DLL. Пробуем код формата, затем базовый код экспорта STEP (3).
|
|
/// </summary>
|
|
private static IConverter GetConverter(IApplication app, int formatCode)
|
|
{
|
|
if (app.Converter[(object)formatCode] is IConverter c) return c;
|
|
// AP-вариант мог не быть отдельным конвертером — берём базовый STEP-экспорт (ksConverterToSTEP = 3).
|
|
if (app.Converter[(object)3] is IConverter cBase) return cBase;
|
|
throw new InvalidOperationException(
|
|
$"get_Converter({formatCode}) вернул null — STEP-конвертер недоступен в этой редакции КОМПАС.");
|
|
}
|
|
}
|