Когда мы смотрим на 3D-модель, то за доли секунды понимаем, что перед нами: «вал», «плита» или «корпус». Мы не измеряем углы и не считаем грани — мозг сопоставляет форму с уже знакомыми паттернами и классифицирует объект.
При этом классификация сама по себе редко является конечной целью. Знать, что это за деталь, интересно для определения конкретных последующих инженерных решений: поиск похожих деталей, выбор технологии изготовления, подбор инструмента, расчёт стоимости или привязка к определённому элементу нормативно-справочной системы.
Именно здесь возникает интерес к автоматизации. Если человек способен распознать тип детали по её геометрии и контексту, то можно ли научить этому программный алгоритм?
Сама тема не новая и подходов к классификации 3D-моделей существует множество, в том числе с использованием нейросетей. Но любое такое решение упирается в баланс между затрачиваемыми ресурсами и качеством результата. Возможно, вместо того чтобы передавать 3D-модель или ее производные напрямую в нейросеть, имеет смысл понять, что мы можем узнать о ней с помощью простых алгоритмов и можно ли это использовать для улучшения результатов.
CAD-модель — это не просто картинка на экране. В отличие от изображения, она изначально создана как структурированное описание геометрии. Внутри неё уже есть информация о размерах, объёме, площади поверхности, положении центра масс и других характеристиках. Часть этих данных можно получить непосредственно средствами CAD-системы, не анализируя изображение и не восстанавливая геометрию из пикселей или треугольной сетки.
Это меняет саму постановку задачи. Вместо того чтобы сразу пытаться «научить нейросеть видеть» деталь, можно сначала преобразовать исходную 3D-модель в компактный набор существенных признаков. Такой набор становится своеобразным цифровым отпечатком модели: не описывает её во всех геометрических подробностях, но позволяет количественно сравнивать разные данные и выявлять характерные признаки.
Например, одна только комбинация габаритов, объёма, площади поверхности и моментов инерции уже может рассказать о модели гораздо больше, чем кажется на первый взгляд. Добавив к ней другие геометрические признаки, можно получить набор данных, на котором уже можно построить правила классификации, поиск аналогов или последующую ML-модель.
В этой статье хочу продемонстрировать вариант подхода: посмотрим, какие данные доступны через API, что физически означает каждая группа данных и как из сырых чисел получается основа для последующих классификаций.
Сложность задачи классификации по данным CAD
Как уже говорилось выше, решать эту задачу можно по-разному: чисто геометрическими методами (габариты, моменты инерции, кривизна), анализом структуры дерева построения, классическим ML или нейросетями на облаке точек (PointNet, DGCNN), либо гибридом — геометрическим фильтром с последующей обработкой LLM.
Для экспериментальных работ я выбрал путь гибридного решения: геометрия даёт признаки, а финальное решение принимает LLM там, где пороговые правила недостаточно надёжны. Роль LLM здесь — интерпретировать смешанные данные, с которыми классический ML справляется хуже: числовые метрики соседствуют со строками метаданных («Вал_ступенчатый», «Круг$d28 ГОСТ 2590-2006;12ХН3А…»), а результат нужен не в виде метки, а в виде выбора и обоснования типового маршрута с обращением к инструментам поиска. LLM умеет соединить все три слоя данных и объяснить решение на естественном языке — это важно для контроля пути принимаемого решения.
Основная проблема в том, что геометрия одной и той же детали может сильно отличаться от файла к файлу — разные примитивы, разная глубина и структура дерева построения. Одну и ту же деталь пользователь может создать множеством разных способов: нарисовать всё в одном эскизе и вытянуть за один шаг; нарисовать часть, вытянуть, а затем размножить массивом; или же сделать грубый эскиз и довести геометрию вырезанием из заготовки-блока. История построения у этих трёх вариантов будет совершенно разной, хотя итоговая деталь — одна и та же.
Если собрать это в три основные сложности:
Вариативность представления. Одна и та же деталь может быть построена из разных примитивов, иметь разную степень детализации дерева построения (feature tree) или вовсе прийти в виде полигональной сетки без истории создания.
Семантический разрыв. Геометрия не всегда однозначно определяет функцию: цилиндр может быть валом, втулкой или крепёжным отверстием — в зависимости от контекста сборки.
Шумные данные. Фаски, скругления, технологические уклоны и мелкие элементы «замусоривают» основные конструктивные признаки.
Именно эта комбинация факторов и подтолкнула меня к гибридной схеме: не пытаться выжать всё из одной геометрии правилами, а дать LLM возможность учитывать контекст, который трудно формализовать в виде порогов.
Три слоя данных КОМПАС-API
Всё, что можно получить о модели через API, можно разделить на три слоя, и у каждого — свой предел возможностей.
Слой 1 — семантика, записанная человеком. То, что автор модели вписал вручную: обозначение, наименование, материал. Самый простой слой, но и самый ненадёжный: наименование может быть пустым, обобщённым («Деталь», «Сборочная единица») или просто неверным.
Слой 2 — физика, вычисленная CAD-ядром. То, что ядро КОМПАС-3D вычисляет из геометрии само: габариты, масса, объём, моменты инерции. Эти данные объективны и не зависят от дисциплины автора модели, но требуют интерпретации — сами по себе числа ничего не «говорят» о типе детали.
Слой 3 — вычисляемые, производные признаки. Производные данные, которые считаются на базе данных слоя 2 (масс-инерционные характеристики, габариты, описание граней): доли типов поверхностей, отношения сторон, признаки осевой и отражательной симметрии. Самый информативный слой для классификации, но и самый затратный по вычислениям.
Ключевая идея подхода: ни один слой сам по себе не даёт надёжной классификации, нужно работать с их комбинацией, упакованной в единую «цифровую сводку» модели.
Слой 1. Семантика, записанная человеком: обозначение, наименование, материал
Свойства документа доступны через Интерфейс IPropertyMng. Идея простая — получить свойства детали, которые нам нужны по их ID. Все идентификаторы приведены в разделе справки SystemPropertyType — номера системных свойств.
Пример кода функции
procedure ExtractPartMetadata(topPart7: IPart7; out Designator, Name, ObjectType: string; out MaterialRaw: string); var propMng: IPropertyMng; propKeeper: IPropertyKeeper; prop: IProperty; libVariant, indexVariant, oVar: OleVariant; flag: WordBool; i, propCnt: Integer; begin Designator := ''; Name := ''; ObjectType := ''; MaterialRaw := ''; propMng := KompasApi7 as IPropertyMng; propKeeper := topPart7 as IPropertyKeeper; TVariantArg(libVariant).vt := VT_EMPTY; TVariantArg(indexVariant).vt := VT_R8; propCnt := propMng.PropertyCount[libVariant]; for i := 0 to propCnt - 1 do begin indexVariant := i; prop := propMng.GetProperty[libVariant, indexVariant]; if not Assigned(prop) then Continue; propKeeper.GetPropertyValue(prop, oVar, False, flag); if not flag then Continue; // свойство не заполнено — пропускаем case Round(prop.ID) of 4: Designator := VarToStr(oVar); // 4 — Обозначение 5: Name := VarToStr(oVar); // 5 — Наименование 9: MaterialRaw := VarToStr(oVar); // 9 — Материал 14: ObjectType := VarToStr(oVar); // 14 — Тип объекта end; end; end;
Здесь есть тонкость, из-за которой этот слой нельзя использовать как основной источник классификации: наименование заполняется человеком и не стандартизировано. «Вал», «Вал_ступенчатый», «Деталь 001» — с точки зрения API это просто строки, семантику которых система не понимает.
Материал — более структурированные данные. Строка вида Круг$d28 ГОСТ 2590-2006;12ХН3А ТУ 14-1-950-86$ раскладывается на сортамент, размер, марку и стандарт:
Строка материала | Сортамент | Размер | Марка | Стандарт |
|---|---|---|---|---|
| Круг | 28 | 12ХН3А | ГОСТ 2590-2006 / ТУ 14-1-950-86 |
| Лист | 10x5 | Ст3сп | ГОСТ 19903-2015 / ГОСТ 380-2005 |
| — | — | 12Х18Н10Т | ГОСТ 5632-2014 |
В тексте встречаются специальные символы форматирования, которые относятся к формирования спецзнаков и дробей, детали форматирования указаны в справке Str - Текст в виде строки.
Материал полезен как дополнительный признак для LLM на финальном шаге: «круг Ø28» уже намекает на тело вращения ещё до анализа геометрии.
Слой 2. Физика, вычисленная CAD-ядром: от чисел к геометрическому смыслу
Слой 2 не зависит от аккуратности автора модели — значения вычисляет ядро КОМПАС-3D.
Габариты. Метод IPart7.GetGabarit — Выдать габарит возвращает координаты ограничивающего параллелепипеда, из которых получаются длина, ширина и высота модели. Простая, но уже полезная информация: вытянутая вдоль одной оси форма — кандидат в валы, близкая к кубу — кандидат в корпуса.
Масс-инерционные характеристики. Интерфейс IMassInertiaParam7 — массово-центровочные характеристики даёт массу, объём, площадь поверхности, координаты центра масс и моменты инерции. Прежде чем использовать последние, важно понимать, в какой системе координат КОМПАС возвращает каждую группу величин: от этого зависит корректность критериев. Чтобы плотная математика не отпугнула, разберу этот слой в два шага: сначала — что именно отдаёт API, затем — почему на этих числах строятся критерии.
Что говорит API
Групп величин три (контракт IMassInertiaParam7, по каждому свойству есть отдельная страница в разделе «свойства»):
Свойства | Система координат | Геометрический смысл |
|---|---|---|
| Исходная (глобальная) | Оси проходят через начало координат модели |
| Центральная | Начало в центре масс, оси параллельны осям исходной СК |
| Главная центральная | Собственные оси тензора инерции (главные моменты) |
| Исходная | Координаты центра масс |
Это не три независимых набора чисел, а один и тот же тензор инерции в разных осях. В исходной СК он выглядит так:
T = | Lx −Lxy −Lxz | | −Lxy Ly −Lyz | | −Lxz −Lyz Lz |
Переход к центральной СК выполняется теоремой Гюйгенса–Штейнера: если m — масса, а (Xc, Yc, Zc) — центр масс, то
Jx = Lx − m·(Yc² + Zc²)Jxy = Lxy − m·Xc·Yc
и аналогично для остальных компонент. Наконец, Jx0, Jy0, Jz0 — собственные значения тензора в центральной СК; диагонализовать его вручную не нужно, КОМПАС отдаёт главные моменты готовыми. Они инвариантны к повороту детали относительно СК модели, но не содержат информации о направлении главных осей.
MassParam7 := topPart7 as IMassInertiaParam7; if not MassParam7.Actual then MassParam7.Calculate; Mass := MassParam7.Mass; Volume := MassParam7.Volume; Xc := MassParam7.Xc; Yc := MassParam7.Yc; Zc := MassParam7.Zc; // Центральная СК: начало в центре масс, оси параллельны осям модели Jx := MassParam7.Jx; Jy := MassParam7.Jy; Jz := MassParam7.Jz; Jxy := MassParam7.Jxy; Jxz := MassParam7.Jxz; Jyz := MassParam7.Jyz; // Главные центральные моменты (собственные значения тензора) Jx0 := MassParam7.Jx0; Jy0 := MassParam7.Jy0; Jz0 := MassParam7.Jz0;
Если совсем коротко: L* зависят от того, где в модели находится начало координат, J* — от распределения массы вокруг центра масс детали, а J*0 — «чистые» главные значения тензора, одинаковые при любом повороте детали. Это свойство дальше превратится в критерии классификации.
Зачем нужны моменты инерции
Моменты инерции дают строгий физический критерий тела вращения — то, что инженер определяет «на глаз» мгновенно, а по одним габаритам понять невозможно.
Физика критерия: у тела вращения в системе главных центральных осей два момента инерции, перпендикулярных оси симметрии, равны, а центробежные моменты, соответствующие оси вращения, равны нулю. Для каждой точки (x, y, z) тела с осевой симметрией относительно Z найдётся симметричная точка (−x, −y, z) той же плотности, поэтому интегралы ∫xz·dm и ∫yz·dm взаимно уничтожаются. Это и есть математическое выражение того, что человек видит интуитивно.
Какой критерий использовать в коде. Самый чистый способ — сравнить главные моменты Jx0/Jy0/Jz0: у тела вращения два из них равны независимо от того, как деталь повёрнута в модели. Но главные моменты не говорят, какая ось модели является осью вращения. Если ось предполагается параллельной одной из осей модели (типичный случай — вал, построенный вдоль оси), проще работать в центральной СК с Jx/Jy/Jz и центробежными моментами:
AbsThreshold := 0.05 * Max(Jx, Max(Jy, Jz)); CentrifThreshold := 0.01 * Max(Jx, Max(Jy, Jz)); // Ось Z: Jx ≈ Jy, а центробежные моменты в центральной СК близки к нулю. // Для оси X проверяется пара (Jy, Jz) и моменты (Jxy, Jxz), // для оси Y — пара (Jx, Jz) и моменты (Jxy, Jyz). if (Abs(Jx - Jy) <= AbsThreshold) and (Abs(Jxz) <= CentrifThreshold) and (Abs(Jyz) <= CentrifThreshold) then AxisOfRotation := 'Z';
Почему именно Jxz, Jyz, а не глобальные Lxz, Lyz? Центр масс тела вращения лежит на его оси, поэтому в центральной СК симметрия относительно любой плоскости, содержащей ось, обнуляет соответствующие центробежные моменты строго, независимо от того, где в модели расположено начало координат. Глобальные Lxz, Lyz тоже дадут ноль, но только если ось вращения совпадает с осью Z модели: тогда координатные плоскости XZ и YZ содержат ось, и отражения x → −x, y → −y — симметрии тела. Стоит детали быть построенной со сдвигом поперёк оси — и глобальные моменты перестают быть нулевыми, хотя тело вращения не перестаёт им быть. Центральные моменты от положения начала координат не зависят.
Почему это работает даже для шестерён и резьбовых деталей? Критерий опирается на распределение массы, а не на тип поверхностей — шестерня, крыльчатка и резьбовая деталь остаются телами вращения, и моменты инерции это подтверждают. Дополнительно отсекаются кубоиды — если все три момента примерно равны, ось вращения не определена, и это тоже полезный сигнал.
Откуда взялись пороги 5% и 1%. Здесь важно не смешивать два разных утверждения. Физический критерий строг: у идеального тела вращения два главных момента равны точно, а центробежные моменты, соответствующие оси, равны точно нулю. Любое отклонение от этого — либо численная аппроксимация интегралов в КОМПАС (поверхности, по которым считаются моменты, разбиваются на элементы), либо реальная асимметрия детали: шпоночный паз, отверстие под крепёж, лыска, фаска.
Конкретные значения в коде выше — эмпирические эвристики, а не вывод из физики:
5% для моментов (
AbsThreshold) — компромисс: достаточно большой, чтобы не отсечь вал с пазом или отверстием (их вклад в моменты инерции обычно не превышает нескольких процентов), и достаточно малый, чтобы не принять за тело вращения заметно несимметричную деталь: у куба или параллелепипеда с сильно разными рёбрами разность моментов — десятки и сотни процентов.1% для центробежных (
CentrifThreshold) — центробежные моменты тела вращения должны быть нулевыми точно, а не «примерно равными»: они обнуляются за счёт попарного уничтожения вкладов симметричных точек, и у любой заметной асимметрии значение растёт быстро. Поэтому порог здесь на порядок жёстче, чем для моментов.
Здесь нужны две оговорки. Во-первых, равенство двух моментов — необходимое, но не достаточное условие осевой симметрии: квадратная или правильная треугольная призма тоже имеет два равных главных момента, но телом вращения не является. Для классификации это не страшно: признак работает как фильтр, а спорные случаи добираются следующими слоями (доли поверхностей, LLM). Во-вторых, Jx/Jy/Jz — центральные, но не главные моменты: если деталь — тело вращения, ось которого не параллельна осям модели, равенство конкретной пары (Jx ≈ Jy и т.п.) не выполнится ни для одной оси модели. Тогда корректнее опираться на Jx0/Jy0/Jz0, пожертвовав информацией о направлении оси.
Плоскости отражательной симметрии
Здесь работает тот же приём, но с одним дополнением. Если тело симметрично относительно плоскости XZ (отражение y → −y), то вклады точек (x, y, z) и (x, −y, z) в интегралы ∫xy·dm и ∫yz·dm равны по модулю и противоположны по знаку — то есть Jxy = Jyz = 0. Но это верно, только если плоскость симметрии проходит через начало координат, в котором считается тензор. Плоскость симметрии всегда проходит через центр масс, а вот начало координат модели может быть где угодно, поэтому глобальные Lxy, Lyz нулями не будут. Отсюда алгоритм: привести центробежные моменты к центральной СК (теорема Гюйгенса–Штейнера) и проверить пары с координатами центра масс:
плоскость XY (нормаль Z): Zc ≈ 0, Jxz ≈ 0, Jyz ≈ 0 плоскость XZ (нормаль Y): Yc ≈ 0, Jxy ≈ 0, Jyz ≈ 0 плоскость YZ (нормаль X): Xc ≈ 0, Jxy ≈ 0, Jxz ≈ 0
Проверка координат центра масс нужна, чтобы не выдать «плоскость» для тела, у которого центробежные моменты случайно малы, а центр масс не лежит в плоскости:
// Приведение L → J: теорема Гюйгенса–Штейнера Jxy := Lxy - Mass * Xc * Yc; Jxz := Lxz - Mass * Xc * Zc; Jyz := Lyz - Mass * Yc * Zc; if (Abs(Zc) <= CoordThreshold) and (Abs(Jxz) <= CentrifThreshold) and (Abs(Jyz) <= CentrifThreshold) then PlanesOfSymmetry.Add('XY'); if (Abs(Yc) <= CoordThreshold) and (Abs(Jxy) <= CentrifThreshold) and (Abs(Jyz) <= CentrifThreshold) then PlanesOfSymmetry.Add('XZ'); if (Abs(Xc) <= CoordThreshold) and (Abs(Jxy) <= CentrifThreshold) and (Abs(Jxz) <= CentrifThreshold) then PlanesOfSymmetry.Add('YZ');
Действует та же оговорка: нулевые центробежные моменты — необходимое, но не достаточное условие плоскости симметрии (они могут обнулиться случайно или за счёт симметрии более высокого порядка). Поэтому найденные плоскости — кандидаты, которые подтверждаются следующими слоями: долями поверхностей из раздела 4 и, в спорных случаях, LLM.
Слой 3. Вычисляемые признаки и «цифровой отпечаток»
Слой 3 опирается на описание граней, которое отдаёт ядро: через дерево построения (интерфейс IFeature7 — объект дерева построения) для каждой грани (интерфейс IFace) можно узнать тип математической поверхности и её площадь. На основе этих данных уже можно вычислить признаки слоя 3 — какие типы поверхностей составляют модель и в каких пропорциях:
featureRoot := topPart7 as IFeature7; objVariant := featureRoot.ModelObjects[ksObjectUnknown]; for i := VarArrayLowBound(objVariant, 1) to VarArrayHighBound(objVariant, 1) do if Supports(IDispatch(objVariant[i]), IModelObject, modelObj) then if modelObj.ModelObjectType = o3d_face then begin face7 := modelObj as IFace; AddSurface(GetMathSurface3DTypeName(face7.BaseSurface3DType), face7.GetArea(ksLUnMM)); end;
Код обходит дерево построения: свойство ModelObjects интерфейса IFeature7 возвращает массив модельных объектов, каждый из которых приводится к базовому интерфейсу IModelObject. Свойство ModelObjectType отбирает только грани — константа o3d_face из перечисления Obj3dType. Сама грань работает через интерфейс IFace: тип математической поверхности возвращает свойство BaseSurface3DType, площадь — метод GetArea (единицы измерения — перечисление ksLengthUnitsEnum, ksLUnMM — миллиметры).
КОМПАС-3D различает более 40 типов математических поверхностей — полный список значений приведён в перечислении ksMathSurface3DTypeEnum. Для базовых алгоритмов классификации важны немногие:
Тип поверхности | Описание | Характерна для |
|---|---|---|
| Плоскость | Призматические детали, плиты |
| Цилиндр | Валы, отверстия, оси |
| Конус | Фаски, конические переходы |
| Тор | Скругления, канавки |
| Поверхность вращения | Фасонные тела вращения |
| Выдавливание | Зубья, пазы |
| Кинематическая | Резьба, шлицы |
Из площадей по типам и габаритов считается набор безразмерных метрик — тот самый «цифровой отпечаток» детали:
Отношения сторон (
L/W,L/H,W/H) — насколько деталь вытянута вдоль каждой оси. Эмпирический ориентир для типовой машиностроительной номенклатуры: у валаL/Wобычно 5–20, у плиты — 0.5–2.0. Это наблюдение, а не теоретическая граница: для другого парка деталей (например, мелкие детали электроники) диапазоны будут другими.Surface-to-Volume (площадь / объём) — характеристика компактности формы: чем больше поверхность относительно объёма, тем менее компактна деталь при прочих равных. Тонкостенные и разветвлённые тела дают высокое значение, компактные — низкое.
Доли типов поверхностей — суммарная площадь каждого типа, нормированная на общую площадь. Ориентиры тоже эмпирические: у вала цилиндрическая доля обычно выше 70%, у плиты плоская доля — выше 80%. На своей номенклатуре их нужно пересчитывать, а не переносить как константы.
Осевая симметрия и плоскости симметрии — булевы и категориальные признаки из раздела 3.
SymmetryScore — метрика «кубичности» формы: насколько три габарита близки друг к другу (1.0 — куб, 0.0 — хотя бы одна пара размеров сильно различается). Считается как среднее относительное расхождение пар размеров, вычтенное из единицы:
SymmetryScore = 1 − ( |L−W|/max(L,W) + |L−H|/max(L,H) + |W−H|/max(W,H) ) / 3
Каждый член — расхождение пары размеров, нормированное на больший из них, поэтому метрика безразмерна и не зависит от масштаба детали. Это метрика изометричности, её не стоит путать с отражательной симметрией — та считается отдельно (is_axisymmetric, planes_of_symmetry).
«Цифровой отпечаток»: что именно собирается
Чтобы «цифровой отпечаток» не остался абстракцией, ниже приведу пример групп и полей, который собирает все три слоя данных в один JSON-документ.
Каждое поле документа привязано к одному из трёх слоёв из раздела 1: семантика, записанная человеком (слой 1), физика, вычисленная CAD-ядром (слой 2), и признаки, вычисленные нами (слой 3):
Группа | Поля | Слой, происхождение |
|---|---|---|
|
| слой 1 — семантика, записанная человеком ( |
|
| слой 1 (строка) + парсинг строки — слой 3 |
|
| слой 2 — |
|
| слой 2 — |
|
| слой 2 — обход граней |
|
| слой 3 — формулы из этого раздела |
|
| слой 3 — критерии из раздела 3 |
Сравнение метрик ролика и стенка
Для демонстрации взяты две контрастные 3D-модели:

Часть метрик обеих моделей сведены в таблицу для наглядности различий:
Метрика | Ролик | Стенка | Что показывает |
|---|---|---|---|
Габариты L×W×H, мм | 50 × 70 × 70 | 838 × 58 × 70 | — |
AspectRatio LW | 0.71 | 14.4 | Ролик компактный: длина вдоль оси (50 мм) меньше диаметра (70 мм); стенка вытянута вдоль X |
AspectRatio WH | 1.00 | 0.83 | Сечение ролика круглое: W = H = 70 |
SurfaceToVolume | 0.28 | 0.54 | Стенка — «развёрнутая» тонкостенная форма, менее компактная |
CylinderSurfaceRatio | 0.41 | 0.012 | У ролика цилиндры — основной тип поверхности; у стенки цилиндры — только отверстия |
PlaneSurfaceRatio | 0.28 | 0.99 | Стенка почти целиком состоит из плоскостей |
ConeSurfaceRatio | 0.26 | 0.00 | Конические фаски и переходы ролика |
IsAxisymmetric | Да (ось X) | Нет | Ролик — тело вращения |
SymmetryScore | 0.81 | 0.33 | У ролика два поперечных размера равны (вклад пары W, H обнуляется), у стенки все три размера разные |
Разделение достигается последовательностью фильтров, а не одной формулой. Первым срабатывает физический критерий IsAxisymmetric: ролик проходит, стенка — нет и выпадает из класса тел вращения ещё до анализа долей поверхностей. Признак подтверждается с двух сторон — геометрией (поперечные размеры ролика равны, W = H = 70, aspect_ratio_wh = 1.00) и физикой (пара центральных моментов jy ≈ jz при нулевых центробежных). Состав поверхностей уточняет картину: ролик — не чистый цилиндр, а смесь цилиндров (41%), конических фасок и переходов (26%), торцевых плоскостей (28%) и торов (5%) — характерный облик обработанного тела вращения; стенка — почти чистые плоскости (99%) с 1.2% цилиндров (это поверхности отверстий).
Пример показывает и почему одиночные признаки обманчивы: CylinderSurfaceRatio ролика — 0.41 при «валовом» ориентире «выше 70%» из раздела 4, а стенка с AspectRatio LW = 14.4 попадает в «валовый» диапазон 5–20, тогда как сам ролик (0.71) выглядит «как плита» — по одному признаку их легко перепутать с валом и плитой соответственно. Полезны признаки только в связке, поэтому первичный фильтр — IsAxisymmetric, не зависящий от того, как площадь поделена между типами поверхностей. Здесь же проходит граница пороговых правил: на ролике пороговый классификатор, настроенный на чистые валы, ошибся бы, и решение разумно передать LLM — она оценивает комбинацию признаков целиком, вместе с текстовыми данными (материал Круг Ø70 ГОСТ 2590-2006; 40Х13-б ГОСТ 5949-75 — круглый прокат, уже намекающий на тело вращения).
Опыты с LLM
В принципе, полученный JSON содержит уже много данных, и следующим шагом были предприняты попытки использовать уже большую языковую модель для классификации объекта по какому-то классификатору. В машиностроении есть несколько стандартов — Технологический классификатор деталей (ОК 021-95), работающий в связке с Классификатором ЕСКД (OK 012-93).
К сожалению, попытки получить релевантный ответ от модели, допустим, с готовым кодом ЕСКД или каким-то понятным кодом фасета из ЕСТД, не приносят нужного результата.
Первые разряды кода ЕСТД (классы 71–76) — это, по сути, конструктивная геометрия, и на основе наших метрик LLM определяют её без каких-либо сложностей:
Класс ЕСКД | Наименование | Признаки из API |
|---|---|---|
71 | Тела вращения (валы, втулки, диски) |
|
73/74 | Корпусные и плоскостные детали |
|
75 | Сложные детали (кулачки, пружины) | Смешанные типы поверхностей, наличие |
Но дальше классификация с помощью подготовленных данных упирается в потолок. Например, по коду ЕСТД нужны локальные конструктивные признаки: тип резьбы (метрическая или трубная), вид отверстия (глухое или сквозное), наличие шпоночного паза или зубчатого венца. В нашем JSON всё это либо не различимо, либо теряется в статистике:
резьба и шлицы для ядра КОМПАС — один и тот же тип поверхности,
ksEvolutionSurface;глухое и сквозное отверстия дают одинаковую цилиндрическую площадь, если совпадают диаметры;
шпоночный паз занимает ничтожную долю общей площади и просто теряется в общей статистике.
Попытки передачи LLM вместе с изображением чертежа — виды, разрезы, сечения, так же не приносят желаемого результата. Даже сильные мультимодальные модели путаются в инженерной графике: принимают линию невидимого контура за реальную грань, промахиваются с размером, пропускают знак допуска формы. Чертёж — это язык условностей, и попытка заставить языковую модель «прочитать» его целиком быстро превращается в галлюцинации, которые нечем проверить.
Вариант, который я вижу дальше — не обучать одну универсальную vision-модель «узнавать деталь целиком» (это возвращает нас к проблемам классических PointNet/DGCNN-подходов из раздела «Сложность задачи»), а обучить набор узкоспециализированных моделей-классификаторов, каждая из которых отвечает на один бинарный или категориальный вопрос: «есть ли на этом виде резьба», «это отверстие глухое или сквозное», «здесь зубчатый профиль или просто рифление». Маленькие модели под узкую задачу требуют кратно меньше размеченных данных, обучаются быстрее и, что важнее, дают предсказуемые, объяснимые ошибки, которые проще ловить порогом уверенности.
Входные данные для таких моделей не нужно готовить отдельно: тот же КОМПАС-API, который отдаёт геометрию, может сгенерировать нужные проекционные 2D-виды детали программно — фронтальный, профильный, вид с разрезом по оси, — без участия человека. Это сохраняет главный принцип всего подхода: минимум ручной работы, максимум переиспользования уже доступных API-возможностей.
Логика вызова — не «прогонять через vision-модель каждую деталь», а обращаться к ней точечно, когда LLM-агенту это действительно нужно для решения. Возвращаясь к кейсу из раздела 5: у ролика IsAxisymmetric = true, но CylinderSurfaceRatio — всего 0.41, то есть ровно та ситуация «тело вращения с большим вкладом нецилиндрических поверхностей», где одиночные пороги начинают ошибаться. А если на такой детали есть резьба, её не увидит ни один порог по долям — тип ksEvolutionSurface не отличает резьбу от шлицев (см. выше). Это ровно та точка, где агент вместо того, чтобы гадать по порогам, сам решает вызвать inspect_feature с feature_hint: thread_presence и получить прямой ответ вместо косвенного. Таким образом, дорогой vision-инструмент подключается адресно — только там, где слои 1–3 действительно исчерпали себя, а не по умолчанию для каждой модели.
Заключение
Исходя из проведенных экспериментов, можно сказать, что CAD-модель содержит существенно больше информации, чем доступно при её представлении в виде изображения, полигональной сетки или воксельной модели. Значительная часть признаков, необходимых для первичной классификации деталей, уже вычисляется ядром КОМПАС-3D и может быть получена непосредственно через API.
Наиболее интересным представляется многоуровневый подход, в котором данные разделяются на несколько взаимодополняющих слоев: семантику, заданную пользователем, физические характеристики, вычисленные CAD-ядром, и производные геометрические признаки. Их объединение в единую цифровую сводку позволяет перейти к содержательному описанию формы детали.
В то же время эксперименты показывают принципиальное ограничение такого представления. Статистическое описание геометрии хорошо работает для определения общих конструктивных классов, но начинает терять информацию о локальных признаках, которые необходимы для более глубокой классификации: типе резьбы, глухом или сквозном отверстии, шпоночном пазе, зубчатом профиле и других элементах.
Открытым остаётся вопрос локальных конструктивных признаков — резьбы, типа отверстия, зубчатого профиля, — которые в API либо неразличимы, либо теряются в общей массе данных. Здесь на первый план выходит следующий инструмент: узкоспециализированные модели-классификаторы, работающие с 2D-проекциями, которые тот же API КОМПАС-3D способен сгенерировать программно. Но описание решения подобной задачи тема для следующей статьи.

