docs: типы отверстий (цековка/зенковка) — README/CLAUDE/ARCHITECTURE/OPEN_QUESTIONS/presentation; счётчики 69 инструментов, 118 тестов (исправлен ошибочный подсчёт 89)
This commit is contained in:
@@ -25,7 +25,7 @@ The base is committed to the repo (canonical) — no regeneration step. It cover
|
||||
|
||||
**v1 + v2 + STEP/assembly + direct B-rep edit + structural model inspection implemented and working** (full sketch→feature→inspect→STEP round-trip + move_face + describe_model validated end-to-end). Stack:
|
||||
**.NET 8 (`net8.0-windows`, x64), C#**, MCP via the official `ModelContextProtocol` SDK over **stdio**.
|
||||
**67 MCP tools, 116 tests green (69 unit + 47 integration).** v2 added: sketch-on-face (by point and by index), revolve (boss/cut + sketch axis), fillet/chamfer (edge-by-point and by index), and Query tools `get_part_info` (МЦХ), `get_bounding_box`, `list_faces`, `list_edges`. After v2: `import_step`, `export_step` (`ConversionService`, `ConversionTools`), `list_components` (assembly traversal via `TopPart → IParts7`). `move_face` (`FaceEditService`, `EditTools`) — direct B-rep face editing. After move_face: **structural model inspection** — `describe_model`, `list_features`, `list_bodies`, `list_variables`, `describe_face`, `describe_edge`, `measure` (`ModelInspectionService`, `InspectionTools`). `describe_model` is the preferred first call over `model_snapshot` (no token cost for image context; gives feature tree, bodies, variables, topology summary, МЦХ). Package A «richer sketches»: 7 new sketch primitives — `sketch_add_arc`, `sketch_add_arc_3points`, `sketch_add_ellipse`, `sketch_add_polyline`, `sketch_add_polygon`, `sketch_add_spline`, `sketch_add_point`. `PartModeler` refactored into partial classes: `PartModeler.cs` (core), `PartModeler.Sketch.cs` (2D primitives), `PartModeler.Features.cs` (extrude/revolve/fillet/chamfer). Static `SketchGeometry` class in `Core/Modeling`. Package B «forming ops» complete: **`shell`** (оболочка, `o3d_shellOperation=43`) + **`rib`** (ребро жёсткости, `o3d_ribOperation=44`) + **`sweep`** (кинематическая операция, `o3d_baseEvolution=45`) + **`loft`** (по сечениям, `o3d_baseLoft=30`). Auxiliary geometry (start of package E): **`sketch_create_on_offset_plane`** (смещённая плоскость, `o3d_planeOffset=14`) — unlocked `loft`. Additional Edit tools: **`split_solid_by_plane`**, **`move_body`**, **`boolean_union`**. Package C «patterns & mirror» complete: **`linear_pattern`** (линейный массив, `o3d_meshCopy=35`) + **`circular_pattern`** (круговой массив, `o3d_circularCopy=36`) + **`mirror_operation`** (зеркальная копия операций, `o3d_mirrorOperation=48`) + **`mirror_body`** (зеркало тела, `o3d_mirrorAllOperation=49`). **`hole`** (`HoleService`, `FeatureTools`) — цилиндрическое отверстие (сквозное или глухое) через **API7** (`IModelContainer`/`IHole3D`/`IHoleDisposal`); первая формообразующая операция на API7 (прецедент ранее только у `move_face`). **`draft`** (уклон, `o3d_incline=42`) — наклон граней на угол относительно нейтральной координатной плоскости; реализован через **API5** `ksInclineDefinition` (операция называется Incline в API5, не Draft). Package D «parametrics» started: **`create_variable`**, **`set_variable`**, **`delete_variable`** (`VariableService`, `VariableTools`) — CRUD переменных модели через API5. `list_variables` исправлен (читает `ksPart.GetFeature().VariableCollection`, а не `ksPart.VariableCollection()`). **Ограничение:** переменная управляет геометрией только в параметрической модели (где размеры эскиза связаны с именем переменной); наши эскизы строятся литеральными координатами → `set_variable` хранит/вычисляет значение, но геометрию не меняет. Связь эскизных размеров с переменными (API2D) — не реализована.
|
||||
**69 MCP tools, 118 tests green (69 unit + 49 integration).** v2 added: sketch-on-face (by point and by index), revolve (boss/cut + sketch axis), fillet/chamfer (edge-by-point and by index), and Query tools `get_part_info` (МЦХ), `get_bounding_box`, `list_faces`, `list_edges`. After v2: `import_step`, `export_step` (`ConversionService`, `ConversionTools`), `list_components` (assembly traversal via `TopPart → IParts7`). `move_face` (`FaceEditService`, `EditTools`) — direct B-rep face editing. After move_face: **structural model inspection** — `describe_model`, `list_features`, `list_bodies`, `list_variables`, `describe_face`, `describe_edge`, `measure` (`ModelInspectionService`, `InspectionTools`). `describe_model` is the preferred first call over `model_snapshot` (no token cost for image context; gives feature tree, bodies, variables, topology summary, МЦХ). Package A «richer sketches»: 7 new sketch primitives — `sketch_add_arc`, `sketch_add_arc_3points`, `sketch_add_ellipse`, `sketch_add_polyline`, `sketch_add_polygon`, `sketch_add_spline`, `sketch_add_point`. `PartModeler` refactored into partial classes: `PartModeler.cs` (core), `PartModeler.Sketch.cs` (2D primitives), `PartModeler.Features.cs` (extrude/revolve/fillet/chamfer). Static `SketchGeometry` class in `Core/Modeling`. Package B «forming ops» complete: **`shell`** (оболочка, `o3d_shellOperation=43`) + **`rib`** (ребро жёсткости, `o3d_ribOperation=44`) + **`sweep`** (кинематическая операция, `o3d_baseEvolution=45`) + **`loft`** (по сечениям, `o3d_baseLoft=30`). Auxiliary geometry (start of package E): **`sketch_create_on_offset_plane`** (смещённая плоскость, `o3d_planeOffset=14`) — unlocked `loft`. Additional Edit tools: **`split_solid_by_plane`**, **`move_body`**, **`boolean_union`**. Package C «patterns & mirror» complete: **`linear_pattern`** (линейный массив, `o3d_meshCopy=35`) + **`circular_pattern`** (круговой массив, `o3d_circularCopy=36`) + **`mirror_operation`** (зеркальная копия операций, `o3d_mirrorOperation=48`) + **`mirror_body`** (зеркало тела, `o3d_mirrorAllOperation=49`). **`hole`** (`HoleService`, `FeatureTools`) — цилиндрическое отверстие (сквозное или глухое) через **API7** (`IModelContainer`/`IHole3D`/`IHoleDisposal`); первая формообразующая операция на API7 (прецедент ранее только у `move_face`). **`hole_counterbore`** — отверстие с цековкой (`ksHTCounterbore`, `ISpotfacingHoleParameters`). **`hole_countersink`** — отверстие с зенковкой (`ksHTCountersinking`, `ICountersinkHoleParameters`). `HoleCore` рефакторен: принимает `ksHoleTypeEnum holeType` + `Action<IHole3D> configure` (настройка `HoleParameters` после установки `HoleType`, т.к. параметрический подынтерфейс недоступен до фиксации типа). Базовый `hole` = `ksHTBase` + `configure=null`. **`draft`** (уклон, `o3d_incline=42`) — наклон граней на угол относительно нейтральной координатной плоскости; реализован через **API5** `ksInclineDefinition` (операция называется Incline в API5, не Draft). Package D «parametrics» started: **`create_variable`**, **`set_variable`**, **`delete_variable`** (`VariableService`, `VariableTools`) — CRUD переменных модели через API5. `list_variables` исправлен (читает `ksPart.GetFeature().VariableCollection`, а не `ksPart.VariableCollection()`). **Ограничение:** переменная управляет геометрией только в параметрической модели (где размеры эскиза связаны с именем переменной); наши эскизы строятся литеральными координатами → `set_variable` хранит/вычисляет значение, но геометрию не меняет. Связь эскизных размеров с переменными (API2D) — не реализована.
|
||||
See [`README.md`](README.md) and [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md); design decisions/caveats in
|
||||
[`docs/OPEN_QUESTIONS.md`](docs/OPEN_QUESTIONS.md).
|
||||
|
||||
@@ -53,7 +53,7 @@ Key implementation facts (don't relearn):
|
||||
- **Structural model inspection** (`ModelInspectionService`, `InspectionTools`): `describe_model` — one-call structural "passport" (bounding box + МЦХ + bodies + topology summary + feature tree + variables); preferred over snapshot. `list_features` — feature tree with params (depth/radius/legs). `list_bodies` — list solid/surface bodies with face count. `list_variables` — model variables (name/expression/value, external/info flags); reads via `ksPart.GetFeature().VariableCollection` (all variables, including user-created) with fallback to `ksPart.VariableCollection()` (external-only — bug was fixed). `describe_face` — drill-down by index (type, area, normal, radius, edge count). `describe_edge` — drill-down by index (type, length, adjacent faces, vertices). `measure` — distance/angle between two objects (face|edge|vertex by index, unit `ST_MIX_MM`).
|
||||
- **Variable management (package D start, `VariableService`, `VariableTools`)**: `create_variable(name, value, note?, external?)` — creates a model variable; `set_variable(name, expression)` — sets expression (constant `"30"` or formula `"width*2+5"`); `delete_variable(name)` — deletes (fails if dependents exist). **Key API facts (don't relearn):** variable creation MUST use `ksPart.GetFeature().VariableCollection` (property on root ksFeature) — NOT `ksPart.VariableCollection()` (returns external-only). Expression is the leading field; value is derived. Changes applied via `ksPart.RebuildModel()` (return checked); after rebuild the RCW variable is stale → re-read via fresh collection (`ReadValueFresh`). Dependent variables recalculate automatically. Deletion fails if dependents exist (RemoveVariable returns FALSE). **Geometry limitation:** variables control geometry only in a parametric model where sketch dimensions are linked to variable names; our sketches are built with literal coordinates → `set_variable` stores/computes the value but does NOT change geometry. Linking sketch dimensions to variables (parametric sketches via API2D) is not yet implemented.
|
||||
- **Feature tree API** (don't relearn): read via API5 `ksPart.GetFeature()` → `(ksFeature).SubFeatureCollection(true,false)` → `ksFeatureCollection`. Cast `(ksFeature)part` does NOT work (RCW QI returns null) — must use `GetFeature()`. `ksFeature.type` returns only coarse `o3d_entity` and does NOT distinguish operations; precise type and params come from `ksFeature.GetObject()` → `ksEntity.GetDefinition()` and matching definition type (`ksBossExtrusionDefinition.GetSideParam`, `ksFilletDefinition.radius`, `ksChamferDefinition.GetChamferParam`, …). Node name ("Элемент выдавливания:1", "Скругление:1") is localized by КОМПАС itself.
|
||||
- **STEP import/export, `list_components`, `move_face`, `split_solid_by_plane`, `move_body`, `boolean_union`, full inspection layer, richer sketch primitives (package A), `shell`, `rib`, `sweep`, `loft` (package B complete), `sketch_create_on_offset_plane` (package E start), `linear_pattern`, `circular_pattern`, `mirror_operation`, `mirror_body` (package C complete), `hole` (API7), `draft` (API5 `ksInclineDefinition`), `create_variable`/`set_variable`/`delete_variable` (package D start) are done.** Not yet done: parametric sketches (link sketch dimensions to variable names via API2D — package D continuation), 2D drawing, assembly building; package E continuation (axis, angle plane). Known caveat: boss/cut direction on a selected face depends on face-normal orientation (`forward` may need flipping — agent picks via snapshot or `describe_face` normal). See `docs/OPEN_QUESTIONS.md` → «Ревью v2».
|
||||
- **STEP import/export, `list_components`, `move_face`, `split_solid_by_plane`, `move_body`, `boolean_union`, full inspection layer, richer sketch primitives (package A), `shell`, `rib`, `sweep`, `loft` (package B complete), `sketch_create_on_offset_plane` (package E start), `linear_pattern`, `circular_pattern`, `mirror_operation`, `mirror_body` (package C complete), `hole`, `hole_counterbore`, `hole_countersink` (all API7 via `HoleService`), `draft` (API5 `ksInclineDefinition`), `create_variable`/`set_variable`/`delete_variable` (package D start) are done.** Not yet done: parametric sketches — **investigated, unavailable via COM API** (`ksCDimWithVariable` cannot be constructed from external automation; see `docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md`); 2D drawing, assembly building; package E continuation (axis, angle plane). Known caveat: boss/cut direction on a selected face depends on face-normal orientation (`forward` may need flipping — agent picks via snapshot or `describe_face` normal). See `docs/OPEN_QUESTIONS.md` → «Ревью v2».
|
||||
- **"STEP import without history"** detected structurally: `bodyCount > 0 && no formative features && features.Count <= bodyCount+1` (only origin + body). STEP with edits (move_face: "Смещённая плоскость", "Разрезать", "Переместить грани", "Булева операция") — that already has history.
|
||||
- **Topology/measure API**: `ksFaceDefinition.EdgeCollection` / `GetCylinderParam` / `GetSurface().GetNormal` + `normalOrientation`; `ksEdgeDefinition.GetAdjacentFace(bool)` / `GetVertex(bool)` → `ksVertexDefinition.GetPoint`; bodies via `ksPart.BodyCollection()` → `ksBody` (`IsSolid` / `FaceCollection`); all variables via `ksPart.GetFeature().VariableCollection` → `ksVariable` (external-only: `ksPart.VariableCollection()` — do NOT use for reading all variables); measurements via `ksPart.GetMeasurer()` → `ksMeasurer` (`SetObject1/2`, `unit=ST_MIX_MM`, `Calc`, `distance`/`MinDistance`/`angle` in degrees / `IsAngleValid`).
|
||||
- **STEP import COM pattern** (verified): `IApplication.get_Converter((object)(int)ksConverterFromSTEP=-3)` (pass format code, not DLL path) → `IConverter.ConverterParameters(cmd)` → set `IAdditionConvertParameters.Format=ksConverterFromSTEP` → `IKompasDocument3D1.ConvertFromAdditionFormat(path, prm)`. Export: `ConvertToAdditionFormat` with format codes for AP203/AP214/AP242. Param co-classes (AdditionConvertParameters etc.) are NOT CoCreatable — only via converter factories. Assembly traversal: `IKompasDocument3D.TopPart → IPart7.Parts (IParts7)`. Extract component: `prm.NeedCreateComponentsFiles=true` (writes .m3d files next to STEP) + `IPart7.OpenSourceDocument`.
|
||||
@@ -64,7 +64,7 @@ Key implementation facts (don't relearn):
|
||||
- **Offset plane (`sketch_create_on_offset_plane`, package E start)**: `OpenSketchOnOffsetPlaneAsync` in `PartModeler.Sketch.cs`. `ksPart.NewEntity(o3d_planeOffset=14)` → `ksPlaneOffsetDefinition` (`SetPlane(basePlane)` + `offset` mm + `direction`) → `Create()` → sketch on that plane. Used to place sketches at arbitrary heights — enables `loft` with parallel sections. `entity.Create()` result is checked (reliability fix applied to all `CreateSketchOn*` paths).
|
||||
- **Loft operation (`loft`, package B)**: `ksBaseLoftDefinition` via `ksPart.NewEntity(o3d_baseLoft=30)`. Params: `sketchIds[]` (≥2 closed profile sketches on different parallel planes). `Sketchs().Add(each sketch)` → `SetLoftParam(closed=false, false, true)` → `SetThinParam(false)` → `Create()`. Requires parallel section sketches at different heights — use `sketch_create_on_offset_plane` for the non-base sections.
|
||||
- **Patterns & mirror (package C)**: `linear_pattern` — `ksMeshCopyDefinition` via `ksPart.NewEntity(o3d_meshCopy=35)`; `SetAxis1(axis)` + `SetCopyParamAlongAxis(true,0,count,step,false)` + `count2=1` (disables 2nd direction → 1D linear); features added via `OperationArray()` (no Get). `circular_pattern` — `ksCircularCopyDefinition` via `NewEntity(o3d_circularCopy=36)`; `SetAxis(axis)`; properties set directly: `count1=1` (radial off), `count2=count` (ring), `step2=angle°` between neighbours, `factor2=false`, `inverce=reverse`; `GetOperationArray().Add(feature)`. `mirror_operation` — `ksMirrorCopyDefinition` via `NewEntity(o3d_mirrorOperation=48)`; `SetPlane(basePlane)` + `GetOperationArray().Add(feature)`. `mirror_body` — `ksMirrorCopyAllDefinition` via `NewEntity(o3d_mirrorAllOperation=49)`; `SetPlane(basePlane)`; `ChooseBodies()` does NOT cast to `ksChooseBodies` (returns null) and is not needed — `o3d_mirrorAllOperation` mirrors all bodies keeping the original (volume doubles). Source features retrieved by id from `_features` registry via new private `RequireFeature` helper (analogous to `RequireSketch`). New `src/Kompas.Mcp.Core/Modeling/CoordinateAxis.cs` — enum `CoordinateAxis {X,Y,Z}` + `CoordinateAxes.ToObj3dType/Parse` (→ `o3d_axisOX/OY/OZ = 71/72/73`), analogous to `BasePlane.cs`. `SketchGeometry.RequireMin(int value, int min, string paramName)` — validator for `count>=2`. Empirical: `count` includes the original instance (count=3 → 3 bodies); `count2=1` disables 2nd direction for linear; `step2` is angle° between neighbours for circular.
|
||||
- **Hole operation (`hole`)**: implemented via **API7** (not API5 — `ksHoleDefinition` absent in interop, analogous to `draft`). New service `src/Kompas.Mcp.Core/Modeling/HoleService.cs` (NOT a `PartModeler` method). Tool signature: `hole(x, y, z, diameter, depth=0, throughAll=false)` — simple cylindrical hole (`ksHTBase`), blind or through-all, placed on the face found by world point. Returns confirmation text (no id — hole does NOT enter the `_features` API5 registry). Implementation: `(IModelContainer)part7` (COM-QI) → `Points3D.Add()` creates `IPoint3D` at world coords (centre point) → `Holes3D.Add()` → `IHole3D` (`HoleType=ksHTBase`, `Diameter`, `DepthType=ksDTReachThrough|ksDTValue`, `Depth`, `EndFaceType=ksEFFlat`) → `(IHoleDisposal)hole`: `BaseSurface=face` (via `FindObjectsByPoint`, same as `FaceEditService`), `Perpendicular=true`, `AssociationVertex=point` → `Update()` → `RebuildDocument()`. Placement via `IHoleDisposal` (no position property on `IHole3D`); no placement sketch needed (unlike `extrude_cut`). **Direction selection by volume delta**: `Update()` returns TRUE even when drilling outward (into air, 0 material removed). Strategy: try `Direction=true` → Rebuild → compare volume via API5 `CalcMassInertiaProperties`; if volume did not decrease → try `Direction=false`. Same class of problem as boss/cut face-normal ambiguity. On failure — roll back the orphan point and hole via `IFeature7.Delete()`. Input validation includes `double.IsFinite` check (Infinity passed `>0` guard).
|
||||
- **Hole operations (`hole`, `hole_counterbore`, `hole_countersink`)**: all implemented via **API7** (not API5 — `ksHoleDefinition` absent in interop). Service `src/Kompas.Mcp.Core/Modeling/HoleService.cs`. `HoleCore` helper is parameterised with `ksHoleTypeEnum holeType` + `Action<IHole3D> configure` callback (configure sets `HoleParameters` **after** `HoleType` is assigned, because the type-specific sub-interface — e.g. `ISpotfacingHoleParameters` — is not accessible until the type is fixed). Base `hole` = `ksHTBase` + `configure=null`. `hole_counterbore`: `ksHTCounterbore` + configure sets `(ISpotfacingHoleParameters)hole.HoleParameters` (`SpotfacingDiameter`, `SpotfacingDepth`); validates `spotDiameter>diameter` and `depth>spotDepth` for blind. `hole_countersink`: `ksHTCountersinking` + configure sets `(ICountersinkHoleParameters)hole.HoleParameters` (`CountersinkType=ksCTDiameterAngle`, `CountersinkDiameter`, `CountersinkAngle`); validates `sinkDiameter>diameter`, `0<sinkAngle<180`. All three share common placement logic (`IHoleDisposal`+`Points3D`, direction selection by volume delta, orphan rollback). None enters the `_features` API5 registry → no id returned.
|
||||
- **Draft operation (`draft`)**: implemented via **API5** `ksInclineDefinition` (operation name in API5 is "Incline", not "Draft" — do NOT search for "Draft" in API5 docs). `ksPart.NewEntity(o3d_incline=42)` → `GetDefinition() as ksInclineDefinition` → `FaceArray()` (add faces by index via `SelectFaceByIndex`, range-checked before mutation) → `SetPlane(basePlane)` → `angle` (degrees) → `direction` → `Create()` → register in `_features`. Empirical: `direction=false`=expanding (outward, adds material), `direction=true`=tapering (inward) — **opposite to the SDK docs** → mapping in code: `def.direction = !outward`. Neutral plane set via `SetPlane(base coordinate plane)`. Angle validation: `RequireDraftAngle(0<angle<90, double.IsFinite)`. Returns feature id (registered in `_features` → patterns/mirror from package C apply). Note: `o3d_DraftFromEdges=644` / `IDraftFromEdges` is a different "draft from edge baseline" operation — not used here.
|
||||
- **Richer sketch primitives (package A, ksDocument2D API5 wrappers)**: `ksArcBy3Points` (3-point arc), `ksArcByAngle` (centre/radius/start-end angles in degrees, counterClockwise flag), `ksEllipse` via `ksEllipseParam` — struct obtained via `KompasObject.GetParamStruct(ko_EllipseParam=22)`; **property names are `A`/`B` (uppercase) in the interop**; `ksRegularPolygon` via `ksRegularPolygonParam` (`ko_RegularPolygonParam=92`) — `describe = !inscribed`; NURBS spline via `ksNurbs(order=4)` + `ksNurbsPoint` loop + `ksEndObj`; `ksPoint`. Param structs are released after use. `PartModeler` split into partial classes: `PartModeler.cs` (registry/helpers/NewParam<T>/reset), `PartModeler.Sketch.cs` (all 2D primitives), `PartModeler.Features.cs` (extrude/revolve/fillet/chamfer). Static `SketchGeometry` class (`Core/Modeling`) holds enum mappings (`ArcDirection`, `PolygonDescribe`) and validators (`RequirePositive`, `RequireVertexCount`, `RequirePoints`). Polyline/spline point lists use `record SketchPoint(X, Y)` with JSON names `x`/`y`.
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@ src/Kompas.Mcp.Host/bin/Release/net8.0-windows/kompas-mcp.exe
|
||||
}
|
||||
```
|
||||
|
||||
## Инструменты (67 инструментов)
|
||||
## Инструменты (69 инструментов)
|
||||
|
||||
| Группа | Инструменты |
|
||||
|---|---|
|
||||
| System | `kompas_connect`, `kompas_status`, `kompas_set_visible` |
|
||||
| Documents | `document_create`, `document_open`, `document_save`, `document_save_as`, `document_close`, `document_active` |
|
||||
| Sketch | `sketch_create`, `sketch_create_on_face`, `sketch_create_on_face_index`, `sketch_create_on_offset_plane`, `sketch_add_line`, `sketch_add_circle`, `sketch_add_rectangle`, `sketch_add_axis`, `sketch_add_arc`, `sketch_add_arc_3points`, `sketch_add_ellipse`, `sketch_add_polyline`, `sketch_add_polygon`, `sketch_add_spline`, `sketch_add_point`, `sketch_close` |
|
||||
| Features | `extrude_boss`, `extrude_cut`, `revolve_boss`, `revolve_cut`, `fillet_edge`, `chamfer_edge`, `fillet_edge_index`, `chamfer_edge_index`, `shell`, `rib`, `sweep`, `loft`, `linear_pattern`, `circular_pattern`, `mirror_operation`, `mirror_body`, `hole`, `draft`, `rebuild` |
|
||||
| Features | `extrude_boss`, `extrude_cut`, `revolve_boss`, `revolve_cut`, `fillet_edge`, `chamfer_edge`, `fillet_edge_index`, `chamfer_edge_index`, `shell`, `rib`, `sweep`, `loft`, `linear_pattern`, `circular_pattern`, `mirror_operation`, `mirror_body`, `hole`, `hole_counterbore`, `hole_countersink`, `draft`, `rebuild` |
|
||||
| Edit | `move_face`, `split_solid_by_plane`, `move_body`, `boolean_union` |
|
||||
| Inspection | `describe_model`, `list_features`, `list_bodies`, `list_variables`, `describe_face`, `describe_edge`, `measure` |
|
||||
| Vision | `model_snapshot` (PNG-снимок; fallback — сначала `describe_model`) |
|
||||
@@ -71,7 +71,7 @@ src/Kompas.Mcp.Host/bin/Release/net8.0-windows/kompas-mcp.exe
|
||||
```
|
||||
src/Kompas.Mcp.Core/ COM-слой: STA-диспетчер, подключение, документы, эскизы/операции, конвертация, снимок, инспекция модели
|
||||
src/Kompas.Mcp.Host/ MCP-сервер (stdio) + определения инструментов
|
||||
tests/Kompas.Mcp.Tests/ 116 тестов: unit + integration (integration требуют КОМПАС)
|
||||
tests/Kompas.Mcp.Tests/ 118 тестов: unit + integration (integration требуют КОМПАС)
|
||||
libs/kompas-interop/ вендорские interop-сборки КОМПАС (из SDK Samples/Common)
|
||||
docs/ архитектура, план, презентация, MD-база знаний SDK (Kompas3D_SDK/)
|
||||
usecases/ полигон обкатки подходов (в .gitignore); приёмы поднимаются в навык kompas-3d
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Архитектура MCP-сервера КОМПАС-3D (предлагаемый вариант)
|
||||
|
||||
> Статус: **реализовано и работает** (v1+v2+STEP/assembly+direct-edit+inspection+package-A «богатые эскизы»+package-B «shell+rib+sweep+loft»+package-C «массивы и зеркало»+package-D start «переменные»+package-E «offset plane»+`hole`+`draft`). Актуализировано по коду.
|
||||
> Статус: **реализовано и работает** (v1+v2+STEP/assembly+direct-edit+inspection+package-A «богатые эскизы»+package-B «shell+rib+sweep+loft»+package-C «массивы и зеркало»+package-D start «переменные»+package-E «offset plane»+`hole`+`hole_counterbore`+`hole_countersink`+`draft`). Актуализировано по коду.
|
||||
> Сопутствующий контекст по COM API КОМПАС — в [`../CLAUDE.md`](../CLAUDE.md).
|
||||
> Имена интерфейсов и перечислений сверены со справкой SDK по MD-базе знаний `docs/Kompas3D_SDK/` (навык `kompas-sdk-research`).
|
||||
|
||||
@@ -113,7 +113,7 @@ MCP client ──stdio──> Host (поток-пул, async)
|
||||
|---|---|
|
||||
| **Kompas.Mcp.Host** | Точка входа. Сборка MCP-сервера (stdio), DI (в т.ч. `ConversionService`), логи в stderr, старт и владение STA-потоком, graceful shutdown. Определения инструментов по категориям (System / Documents / Sketch / Features / Query / Conversion). **Тонкий слой**: валидация аргументов → постановка задачи на STA-поток → форматирование результата/ошибки в MCP-ответ. |
|
||||
| **Kompas.Mcp.Core** | COM-слой. Менеджер соединения, менеджер документов, построитель эскизов и операций, `ConversionService` (STEP импорт/экспорт), `QueryService` (МЦХ, грани, рёбра, компоненты), `ModelInspectionService` (дерево операций, тела, переменные, drill-down, измерения), снимок. Все паттерны API5/API7 живут здесь. |
|
||||
| **Kompas.Mcp.Tests** | Юнит (без COM) + интеграционные (требуют КОМПАС). 116 тестов (69 unit + 47 integration). |
|
||||
| **Kompas.Mcp.Tests** | Юнит (без COM) + интеграционные (требуют КОМПАС). 118 тестов (69 unit + 49 integration). |
|
||||
|
||||
Принцип: **только `Core` знает про COM**. `Host`/Tools оперируют доменными DTO и вызывают `Core`; `Host` не содержит бизнес-логики.
|
||||
|
||||
@@ -121,7 +121,7 @@ MCP client ──stdio──> Host (поток-пул, async)
|
||||
|
||||
---
|
||||
|
||||
## 5. Карта инструментов (67 инструментов)
|
||||
## 5. Карта инструментов (69 инструментов)
|
||||
|
||||
Сгруппированы вокруг центрального цикла «эскиз ↔ операция». Имена — `snake_case`.
|
||||
|
||||
@@ -157,6 +157,8 @@ MCP client ──stdio──> Host (поток-пул, async)
|
||||
- `mirror_operation` — зеркальная копия операций (`o3d_mirrorOperation=48`, `ksMirrorCopyDefinition`); параметры: `featureIds[]`, `plane` (XOY/XOZ/YOZ). `SetPlane` + `GetOperationArray()`.
|
||||
- `mirror_body` — зеркало всего тела (`o3d_mirrorAllOperation=49`, `ksMirrorCopyAllDefinition`); параметр: `plane`. `ChooseBodies()` не приводится к `ksChooseBodies` и не нужен — операция отражает все тела, сохраняя оригинал (объём удваивается).
|
||||
- `hole` — цилиндрическое отверстие (сквозное или глухое) на грани, найденной по мировой точке (x,y,z). Параметры: `diameter` (мм), `depth` (мм, для глухого), `throughAll`. Реализовано через **API7** (`HoleService`, `src/Kompas.Mcp.Core/Modeling/HoleService.cs`) — в API5 интерфейс `ksHoleDefinition` отсутствует в interop. Паттерн: `(IModelContainer)part7` → `Points3D.Add()` (центр, `IPoint3D`) → `Holes3D.Add()` → `IHole3D` (`HoleType=ksHTBase`, `Diameter`, `DepthType`, `Depth`, `EndFaceType=ksEFFlat`) → `(IHoleDisposal)hole` (`BaseSurface=грань` через `FindObjectsByPoint`, `Perpendicular=true`, `AssociationVertex=point`) → `Update()` → `RebuildDocument()`. Направление сверления определяется **по факту убыли объёма**: `Direction=true` → Rebuild → сравнить объём (API5 `CalcMassInertiaProperties`); если не убыл → `Direction=false`. При неуспехе — откат через `IFeature7.Delete()`. Возвращает подтверждение без id (отверстие не попадает в реестр `_features` API5).
|
||||
- `hole_counterbore` — отверстие с цековкой (цилиндрическое уширение сверху, под винт с цилиндрической головкой). Параметры: `x,y,z`, `diameter`, `spotfaceDiameter` (>diameter), `spotfaceDepth`, `depth=0`, `throughAll=false`. `HoleType=ksHTCounterbore`; `HoleParameters` приводится к `ISpotfacingHoleParameters` (`SpotfacingDiameter`, `SpotfacingDepth`) — настройка через `configure`-колбэк после фиксации типа. Для глухого: валидируется `depth>spotDepth`.
|
||||
- `hole_countersink` — отверстие с зенковкой (коническое уширение сверху, под винт с потайной головкой). Параметры: `x,y,z`, `diameter`, `sinkDiameter` (>diameter), `sinkAngle` (0<angle<180, типично 90°), `depth=0`, `throughAll=false`. `HoleType=ksHTCountersinking`; `HoleParameters` → `ICountersinkHoleParameters` (`CountersinkType=ksCTDiameterAngle`, `CountersinkDiameter`, `CountersinkAngle`). Все три инструмента отверстий используют общую логику размещения и подбора направления (`HoleCore`).
|
||||
- `draft` — уклон граней на угол `angle` (°, строго 0–90) относительно нейтральной координатной плоскости `neutralPlane` (XOY/XOZ/YOZ). `outward=true` — расширение (добавляет материал), `false` — сужение. Реализовано через **API5** `ksInclineDefinition` (`o3d_incline=42`) — операция называется Incline в API5, а не Draft. Паттерн: `ksPart.NewEntity(o3d_incline)` → `GetDefinition() as ksInclineDefinition` → `FaceArray()` (грани по индексам из `list_faces`) → `SetPlane(базовая координатная плоскость)` → `angle` → `direction=!outward` → `Create()` → регистрация в `_features`. Эмпирика: `direction=false`=расширение, `direction=true`=сужение — **обратно справке** → маппинг `def.direction = !outward`. Валидация: `RequireDraftAngle(0<angle<90)`. Регистрируется в `_features` → применимы массивы и зеркало (пакет C).
|
||||
- `rebuild` — перестроить деталь.
|
||||
|
||||
@@ -334,10 +336,10 @@ dotnet build -c Release -r win-x64 # сборка
|
||||
|
||||
## 10. Дорожная карта
|
||||
|
||||
**Реализовано (v1+v2+STEP/assembly+direct-edit+inspection+package-A+package-B+package-C+package-D start+package-E start+hole+draft):** документы, эскизы (полный набор 2D-примитивов: линия, окружность, дуга, дуга по 3 точкам, прямоугольник, эллипс, ломаная, правильный многоугольник, сплайн NURBS, точка), **вспомогательная геометрия (`sketch_create_on_offset_plane`)**, выдавливание/вырез, вращение, скругление/фаска, **оболочка (`shell`)**, **ребро жёсткости (`rib`)**, **кинематическая операция (`sweep`)**, **операция по сечениям (`loft`)**, **линейный/круговой массив и зеркало (`linear_pattern`, `circular_pattern`, `mirror_operation`, `mirror_body`)**, **отверстие (`hole`, API7)**, **уклон (`draft`, API5 `ksInclineDefinition`)**, снимок; `get_part_info`, `get_bounding_box`, `list_faces`, `list_edges`; `import_step`, `export_step`, `list_components`; **`move_face`**, **`split_solid_by_plane`**, **`move_body`**, **`boolean_union`** (прямое редактирование и булевы операции); **`describe_model`, `list_features`, `list_bodies`, `list_variables`, `describe_face`, `describe_edge`, `measure`** (структурный осмотр модели); **`create_variable`, `set_variable`, `delete_variable`** (управление переменными, package D start).
|
||||
**Реализовано (v1+v2+STEP/assembly+direct-edit+inspection+package-A+package-B+package-C+package-D start+package-E start+hole+hole_counterbore+hole_countersink+draft):** документы, эскизы (полный набор 2D-примитивов: линия, окружность, дуга, дуга по 3 точкам, прямоугольник, эллипс, ломаная, правильный многоугольник, сплайн NURBS, точка), **вспомогательная геометрия (`sketch_create_on_offset_plane`)**, выдавливание/вырез, вращение, скругление/фаска, **оболочка (`shell`)**, **ребро жёсткости (`rib`)**, **кинематическая операция (`sweep`)**, **операция по сечениям (`loft`)**, **линейный/круговой массив и зеркало (`linear_pattern`, `circular_pattern`, `mirror_operation`, `mirror_body`)**, **отверстие (`hole`, API7)**, **цековка (`hole_counterbore`, API7)**, **зенковка (`hole_countersink`, API7)**, **уклон (`draft`, API5 `ksInclineDefinition`)**, снимок; `get_part_info`, `get_bounding_box`, `list_faces`, `list_edges`; `import_step`, `export_step`, `list_components`; **`move_face`**, **`split_solid_by_plane`**, **`move_body`**, **`boolean_union`** (прямое редактирование и булевы операции); **`describe_model`, `list_features`, `list_bodies`, `list_variables`, `describe_face`, `describe_edge`, `measure`** (структурный осмотр модели); **`create_variable`, `set_variable`, `delete_variable`** (управление переменными, package D start).
|
||||
|
||||
**Следующие приоритеты:**
|
||||
1. Пакет D «параметрика» (продолжение) — связь размеров эскизов с переменными (параметрические эскизы через API2D).
|
||||
1. Пакет D «параметрика» (продолжение) — связь размеров эскизов с переменными (параметрические эскизы через API2D). ⚠️ **Исследовано**: `ksCDimWithVariable` недоступен из внешней автоматизации — см. `docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md`.
|
||||
2. Пакет E «вспомогательная геометрия» (продолжение) — ось, точка, плоскость по трём точкам / по углу.
|
||||
3. Рассечение/перемещение тела как MCP-инструменты (`SplitSolids`/`BodyRepositions`) — механика есть, продуктизация не закончена.
|
||||
4. Свойства документа: `IPropertyMng` / `IPropertyKeeper`.
|
||||
|
||||
@@ -162,7 +162,7 @@ stateful-сессии? Пока полагаемся на последовате
|
||||
Примечание: `o3d_DraftFromEdges=644` / `IDraftFromEdges` — это другая операция «уклон от базовой линии» (API7), здесь не используется.
|
||||
|
||||
### ✅ Пакет D «параметрика» — CRUD переменных реализован
|
||||
**Решено (start).** 3 новых инструмента: `create_variable`, `set_variable`, `delete_variable` — `VariableService` (`src/Kompas.Mcp.Core/Modeling/VariableService.cs`) + `VariableTools` (`src/Kompas.Mcp.Host/Tools/VariableTools.cs`). Исправлен `list_variables` в `ModelInspectionService.ReadVariables`. Итог: **67 инструментов, 116 тестов (69 unit + 47 integration).**
|
||||
**Решено (start).** 3 новых инструмента: `create_variable`, `set_variable`, `delete_variable` — `VariableService` (`src/Kompas.Mcp.Core/Modeling/VariableService.cs`) + `VariableTools` (`src/Kompas.Mcp.Host/Tools/VariableTools.cs`). Исправлен `list_variables` в `ModelInspectionService.ReadVariables`. Итог (на тот момент): **67 инструментов, 116 тестов (69 unit + 47 integration).**
|
||||
|
||||
**Ключевые API-тонкости (эмпирика):**
|
||||
- Создание переменной — ТОЛЬКО через `ksPart.GetFeature().VariableCollection` (свойство-коллекция на корневом `ksFeature`). `ksPart.VariableCollection()` (метод) возвращает только **внешние** переменные и непригоден для создания пользовательских.
|
||||
@@ -173,3 +173,9 @@ stateful-сессии? Пока полагаемся на последовате
|
||||
|
||||
**⚠️ Осознанное ограничение — геометрия не меняется:** переменная управляет геометрией только в параметрической модели, где размеры эскизов привязаны к именам переменных. Наши эскизы строятся литеральными координатами — `set_variable` хранит и вычисляет значение, но геометрию НЕ меняет.
|
||||
Связь размеров эскизов с переменными (параметрические эскизы через API2D) — отдельный пласт, **не реализован**. Это осознанно задокументировано; реализация — продолжение пакета D.
|
||||
|
||||
### ✅ Параметрические эскизы (пакет D продолжение) — исследовано, недоступно через COM-API
|
||||
**Исследовано и закрыто.** `ksCDimWithVariable` (размер с переменной) не конструируется из внешней автоматизации — интерфейс недоступен в COM-клиентском режиме. Связать размеры эскиза с именем переменной через API2D невозможно без исполнения кода внутри процесса КОМПАС (plugin). Подробности — `docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md`.
|
||||
|
||||
### ✅ Отверстие с цековкой и зенковкой — реализовано
|
||||
**Решено.** 2 новых инструмента: `hole_counterbore` (`ksHTCounterbore`, `ISpotfacingHoleParameters`) и `hole_countersink` (`ksHTCountersinking`, `ICountersinkHoleParameters`). `HoleCore` рефакторен под `configure`-колбэк. Итог: **69 инструментов, 118 тестов (69 unit + 49 integration).**
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
<!-- HERO -->
|
||||
<header class="hero">
|
||||
<div class="wrap">
|
||||
<span class="badge"><span class="dot" style="background:var(--green);box-shadow:0 0 10px var(--green)"></span> Статус: v3+ работает — эскиз→операции→STEP→сборка→move_face→структурный осмотр→богатые эскизы→shell+rib+sweep+loft+массивы+зеркало+hole+draft+переменные (67 инструментов)</span>
|
||||
<span class="badge"><span class="dot" style="background:var(--green);box-shadow:0 0 10px var(--green)"></span> Статус: v3+ работает — эскиз→операции→STEP→сборка→move_face→структурный осмотр→богатые эскизы→shell+rib+sweep+loft+массивы+зеркало+hole+hole_counterbore+hole_countersink+draft+переменные (69 инструментов)</span>
|
||||
<h1>КОМПАС-3D <span class="g">MCP-сервер</span><br>управление CAD языком LLM</h1>
|
||||
<p class="lead">MCP-сервер, который превращает операции КОМПАС-3D — создание документов,
|
||||
эскизы, 3D-операции, параметры — в инструменты для языковой модели. Под капотом —
|
||||
@@ -261,7 +261,7 @@
|
||||
впереди.</p>
|
||||
|
||||
<div class="prog">
|
||||
<div class="progrow"><span>Общий прогресс</span><span>v3+: STEP · move_face · структурный осмотр · богатые эскизы (пакет A) · shell+rib+sweep+loft (пакет B) · массивы+зеркало (пакет C) · переменные (пакет D start) · offset-plane (пакет E start) · hole (API7) · draft (API5) · навык kompas-3d · 67 инструментов · 116 тестов</span></div>
|
||||
<div class="progrow"><span>Общий прогресс</span><span>v3+: STEP · move_face · структурный осмотр · богатые эскизы (пакет A) · shell+rib+sweep+loft (пакет B) · массивы+зеркало (пакет C) · переменные (пакет D start) · offset-plane (пакет E start) · hole (API7) · hole_counterbore · hole_countersink · draft (API5) · навык kompas-3d · 69 инструментов · 118 тестов</span></div>
|
||||
<div class="bar"><i style="width:97%"></i></div>
|
||||
</div>
|
||||
|
||||
@@ -297,19 +297,19 @@
|
||||
<!-- TOOLS -->
|
||||
<div class="panel">
|
||||
<h3>Инструменты v3+ <span class="tag done">ГОТОВО</span></h3>
|
||||
<p class="meta">67 инструментов, отдаются по MCP-протоколу</p>
|
||||
<p class="meta">69 инструментов, отдаются по MCP-протоколу</p>
|
||||
<ul class="list">
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>System</code>: connect · status · set_visible</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Documents</code>: create · open · save · save_as · close · active</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Sketch</code>: create · on_face (точка/индекс) · <b>on_offset_plane</b> (смещённая плоскость) · add line/circle/arc/arc_3points/rectangle/axis/ellipse/polyline/polygon/spline/point · close</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Features</code>: extrude · revolve · fillet_edge/chamfer_edge (точка + индекс) · <b>shell</b> (оболочка) · <b>rib</b> (ребро жёсткости) · <b>sweep</b> (кинематическая) · <b>loft</b> (по сечениям) · <b>linear_pattern</b> · <b>circular_pattern</b> · <b>mirror_operation</b> · <b>mirror_body</b> · <b>hole</b> (API7) · <b>draft</b> (уклон, API5) · rebuild</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Features</code>: extrude · revolve · fillet_edge/chamfer_edge (точка + индекс) · <b>shell</b> (оболочка) · <b>rib</b> (ребро жёсткости) · <b>sweep</b> (кинематическая) · <b>loft</b> (по сечениям) · <b>linear_pattern</b> · <b>circular_pattern</b> · <b>mirror_operation</b> · <b>mirror_body</b> · <b>hole</b> (API7) · <b>hole_counterbore</b> (цековка, API7) · <b>hole_countersink</b> (зенковка, API7) · <b>draft</b> (уклон, API5) · rebuild</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Edit</code>: move_face · split_solid_by_plane · move_body · boolean_union</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Inspection</code>: describe_model · list_features · list_bodies · list_variables · describe_face · describe_edge · measure</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Vision</code>: model_snapshot 👁️ (fallback)</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Query</code>: get_part_info · get_bounding_box · list_faces · list_edges · list_components</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Variables</code>: <b>create_variable</b> · <b>set_variable</b> · <b>delete_variable</b> (пакет D)</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t"><code>Conversion</code>: import_step · export_step</span></li>
|
||||
<li><span class="mark wip">→</span><span>пакет D продолжение (параметрические эскизы, API2D) · пакет E (ось, угловая плоскость)</span></li>
|
||||
<li><span class="mark wip">→</span><span>пакет E (ось, угловая плоскость) · пакет D параметрика: параметрические эскизы (API2D) — <b>исследовано, недоступно через COM API</b></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
<ul class="list">
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t">Unit-тесты — без COM: диспетчер, enum-маппинг, StepFormat, InspectionText</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t">Интеграционные тесты с КОМПАС: подключение, документы, снимок, цикл, STEP round-trip, сборка, move_face, инспекция</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t">Итого 116 тестов зелёных (69 unit + 47 integration)</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t">Итого 118 тестов зелёных (69 unit + 49 integration)</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t">Сборка <code>kompas-mcp.exe</code>, README с конфигом клиента</span></li>
|
||||
<li class="muted"><span class="mark ok">✓</span><span class="t">Навык <code>kompas-3d</code> (методика) + полигон <code>usecases/</code></span></li>
|
||||
<li><span class="mark todo"></span><span>In-process тест MCP-клиента, релизный publish</span></li>
|
||||
@@ -345,8 +345,9 @@
|
||||
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">пакет B · готово ✓</div><h4>Формообразующие операции</h4><p><b>shell</b> ✓ · <b>rib</b> ✓ · <b>sweep</b> ✓ · <b>loft</b> ✓ (по сечениям) · <b>offset-plane</b> ✓ (пакет E)</p></div>
|
||||
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">пакет C · готово ✓</div><h4>Массивы и зеркало</h4><p><b>linear_pattern</b> ✓ · <b>circular_pattern</b> ✓ · <b>mirror_operation</b> ✓ · <b>mirror_body</b> ✓ · <b>hole</b> ✓ (API7)</p></div>
|
||||
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">draft · готово ✓</div><h4>Уклон</h4><p><b>draft</b> ✓ (API5 <code>ksInclineDefinition</code>, o3d_incline=42) · 64 инструмента · 115 тестов</p></div>
|
||||
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">пакет D start · готово ✓</div><h4>Переменные модели</h4><p><b>create_variable</b> · <b>set_variable</b> · <b>delete_variable</b> (API5 VariableService) · list_variables исправлен · 67 инструментов · 116 тестов</p></div>
|
||||
<div class="tl cur"><div class="ph">далее · в работе</div><h4>пакет D продолжение + пакет E</h4><p>параметрические эскизы (API2D) · вспомогательная геометрия (ось, угловая плоскость)</p></div>
|
||||
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">пакет D start · готово ✓</div><h4>Переменные модели</h4><p><b>create_variable</b> · <b>set_variable</b> · <b>delete_variable</b> (API5 VariableService) · list_variables исправлен · 67 инструментов</p></div>
|
||||
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">отверстия под крепёж · готово ✓</div><h4>Цековка и зенковка</h4><p><b>hole_counterbore</b> (ksHTCounterbore) · <b>hole_countersink</b> (ksHTCountersinking) · HoleCore рефакторен (configure-колбэк) · 69 инструментов · 118 тестов</p></div>
|
||||
<div class="tl cur"><div class="ph">далее · в работе</div><h4>пакет E продолжение</h4><p>вспомогательная геометрия (ось, угловая плоскость) · пакет D параметрика — параметрические эскизы недоступны через COM API</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user