docs: уклон (draft, API5 Incline) — README/CLAUDE/ARCHITECTURE/OPEN_QUESTIONS/presentation, 64 инструмента, 115 тестов

This commit is contained in:
2026-05-27 10:35:16 +03:00
parent 143877c6cc
commit 72045c8a84
5 changed files with 32 additions and 23 deletions
+3 -2
View File
@@ -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**.
**63 MCP tools, 104 tests green (60 unit + 44 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`).
**64 MCP tools, 115 tests green (69 unit + 46 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).
See [`README.md`](README.md) and [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md); design decisions/caveats in
[`docs/OPEN_QUESTIONS.md`](docs/OPEN_QUESTIONS.md).
@@ -52,7 +52,7 @@ Key implementation facts (don't relearn):
- Logs go to **stderr** (stdout is the MCP channel). Integration tests reuse one КОМПАС via `KompasFixture`; artifacts land in gitignored `.scratch/`.
- **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). `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`).
- **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` (package — API7) are done.** Not yet done: `draft` (no API5, requires API7); parametrics (package D), 2D drawing, assembly building. 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` (API7), `draft` (API5 `ksInclineDefinition`) are done.** Not yet done: parametrics (package D), 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`); variables via `ksPart.VariableCollection()``ksVariable`; 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,6 +64,7 @@ Key implementation facts (don't relearn):
- **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).
- **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`.
## КОМПАС-3D API architecture (the critical context)