kompas-kernel 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kompas_kernel/__init__.py +3 -0
- kompas_kernel/features/__init__.py +9 -0
- kompas_kernel/features/assembly_navigator/__init__.py +8 -0
- kompas_kernel/features/assembly_navigator/commands.py +37 -0
- kompas_kernel/features/assembly_navigator/ksapi/__init__.py +5 -0
- kompas_kernel/features/assembly_navigator/ksapi/mapping.py +122 -0
- kompas_kernel/features/assembly_navigator/ksapi/presentation.py +107 -0
- kompas_kernel/features/assembly_navigator/ksapi/raw.py +74 -0
- kompas_kernel/features/assembly_navigator/ksapi/reader.py +287 -0
- kompas_kernel/features/assembly_navigator/ksapi/resolver.py +35 -0
- kompas_kernel/features/assembly_navigator/models.py +218 -0
- kompas_kernel/features/assembly_navigator/queries.py +42 -0
- kompas_kernel/features/assembly_navigator/service.py +31 -0
- kompas_kernel/features/assembly_navigator/summary.py +90 -0
- kompas_kernel/features/document_session/__init__.py +5 -0
- kompas_kernel/features/document_session/checkpointed.py +165 -0
- kompas_kernel/features/document_session/commands.py +94 -0
- kompas_kernel/features/document_session/digest.py +126 -0
- kompas_kernel/features/document_session/ksapi/__init__.py +5 -0
- kompas_kernel/features/document_session/ksapi/context_reader.py +174 -0
- kompas_kernel/features/document_session/ksapi/screenshot.py +365 -0
- kompas_kernel/features/document_session/ksapi/snapshot.py +181 -0
- kompas_kernel/features/document_session/models.py +311 -0
- kompas_kernel/features/document_session/queries.py +62 -0
- kompas_kernel/features/document_session/registry.py +101 -0
- kompas_kernel/features/document_session/service.py +128 -0
- kompas_kernel/features/geometry_3d/__init__.py +9 -0
- kompas_kernel/features/geometry_3d/axis_math.py +50 -0
- kompas_kernel/features/geometry_3d/commands.py +68 -0
- kompas_kernel/features/geometry_3d/hex_detect.py +113 -0
- kompas_kernel/features/geometry_3d/ksapi/__init__.py +5 -0
- kompas_kernel/features/geometry_3d/ksapi/component_geometry.py +559 -0
- kompas_kernel/features/geometry_3d/ksapi/measurements.py +368 -0
- kompas_kernel/features/geometry_3d/ksapi/presentation.py +204 -0
- kompas_kernel/features/geometry_3d/models.py +216 -0
- kompas_kernel/features/geometry_3d/queries.py +96 -0
- kompas_kernel/features/geometry_3d/service.py +69 -0
- kompas_kernel/features/geometry_3d/wrench_zone.py +161 -0
- kompas_kernel/features/ksapi_automation/__init__.py +9 -0
- kompas_kernel/features/ksapi_automation/gate.py +282 -0
- kompas_kernel/features/ksapi_automation/models.py +75 -0
- kompas_kernel/features/ksapi_automation/namespace.py +12 -0
- kompas_kernel/features/ksapi_automation/run_python.py +133 -0
- kompas_kernel/features/ksapi_automation/runner.py +126 -0
- kompas_kernel/features/ksapi_automation/service.py +85 -0
- kompas_kernel/features/part_authoring/__init__.py +5 -0
- kompas_kernel/features/part_authoring/build_geometry.py +122 -0
- kompas_kernel/features/part_authoring/models.py +99 -0
- kompas_kernel/features/wrench_clearance/__init__.py +7 -0
- kompas_kernel/features/wrench_clearance/models.py +87 -0
- kompas_kernel/features/wrench_clearance/service.py +154 -0
- kompas_kernel/kompas/__init__.py +14 -0
- kompas_kernel/kompas/errors.py +11 -0
- kompas_kernel/kompas/models.py +68 -0
- kompas_kernel/kompas/objects.py +93 -0
- kompas_kernel/kompas/platform.py +40 -0
- kompas_kernel/kompas/runtime.py +186 -0
- kompas_kernel/kompas/session.py +195 -0
- kompas_kernel/kompas/units.py +48 -0
- kompas_kernel/ksapi_static/__init__.py +8 -0
- kompas_kernel/ksapi_static/facts.py +132 -0
- kompas_kernel/ksapi_static/inventory.py +185 -0
- kompas_kernel/ksapi_static/recipes.py +114 -0
- kompas_kernel/ksapi_static/wrapper_grep.py +83 -0
- kompas_kernel/observability/__init__.py +1 -0
- kompas_kernel/observability/logger.py +24 -0
- kompas_kernel/observability/setup.py +115 -0
- kompas_kernel/observability/taxonomy.py +27 -0
- kompas_kernel/py.typed +1 -0
- kompas_kernel/standards/__init__.py +1 -0
- kompas_kernel/standards/wrench_clearance.py +234 -0
- kompas_kernel/utils/__init__.py +1 -0
- kompas_kernel/utils/filesystem.py +82 -0
- kompas_kernel/utils/validation.py +21 -0
- kompas_kernel-0.0.1.dist-info/METADATA +56 -0
- kompas_kernel-0.0.1.dist-info/RECORD +77 -0
- kompas_kernel-0.0.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Framework-free public dimension-line commands for geometry 3D, over `KompasSession`.
|
|
2
|
+
|
|
3
|
+
No Pydantic AI, no `kompas_copilot.bridge` import — raw KsAPI presentation lives in
|
|
4
|
+
`ksapi/presentation.py`; this module wires it through session callbacks receiving
|
|
5
|
+
`KompasContext` directly and owns the explicit `ShownDimensionsState` holder that
|
|
6
|
+
`show_distance_dimension`/`clear_dimensions` share.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
|
|
13
|
+
from kompas_kernel.features.geometry_3d.ksapi import presentation
|
|
14
|
+
from kompas_kernel.features.geometry_3d.models import ShowDistanceResult
|
|
15
|
+
from kompas_kernel.kompas.session import KompasContext, KompasSession
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class ShownDimensionsState:
|
|
20
|
+
"""Mutable holder for `IDistanceAngleMeasurement3D` references created by
|
|
21
|
+
`show_distance_dimension` in this session — owned by `GeometryService`, one per
|
|
22
|
+
`KompasSession` (mirrors the field that used to live directly on
|
|
23
|
+
`KompasKsApiAdapter`, `_shown_distance_measurement_references`).
|
|
24
|
+
|
|
25
|
+
`clear_dimensions` below reads and rewrites `.references` INSIDE the same worker
|
|
26
|
+
queue item (`KompasSession.run` callback) as the KsAPI delete calls, not after the
|
|
27
|
+
`await` returns — so two concurrent `clear_dimensions()`/`show_distance_dimension()`
|
|
28
|
+
calls on the same service can never interleave a stale read with a write (the
|
|
29
|
+
property the legacy adapter's `_clear_dimensions` docstring called "update stable
|
|
30
|
+
state in the same queue item").
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
references: list[int] = field(default_factory=list)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def show_distance_dimension(
|
|
37
|
+
session: KompasSession,
|
|
38
|
+
component_identifier_1: str,
|
|
39
|
+
component_identifier_2: str,
|
|
40
|
+
state: ShownDimensionsState,
|
|
41
|
+
) -> ShowDistanceResult:
|
|
42
|
+
"""Показать место зазора: создать ПОСТОЯННУЮ размерную линию между компонентами."""
|
|
43
|
+
|
|
44
|
+
def _operation(context: KompasContext) -> ShowDistanceResult:
|
|
45
|
+
return presentation.show_distance_dimension(
|
|
46
|
+
context.modules,
|
|
47
|
+
context.app,
|
|
48
|
+
component_identifier_1,
|
|
49
|
+
component_identifier_2,
|
|
50
|
+
state.references,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return await session.run(operation_name="geometry_3d.show_distance_dimension", operation=_operation)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def clear_dimensions(session: KompasSession, state: ShownDimensionsState) -> int:
|
|
57
|
+
"""Убрать все размерные линии, созданные `show_distance_dimension` в этой сессии.
|
|
58
|
+
|
|
59
|
+
`state.references` перезаписывается ВНУТРИ того же callback, что и сам вызов
|
|
60
|
+
`IFeature.Delete()` (см. `ShownDimensionsState` докстринг) — не после `await`.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def _operation(context: KompasContext) -> int:
|
|
64
|
+
deleted, remaining = presentation.clear_dimensions(context.modules, context.app, state.references)
|
|
65
|
+
state.references = remaining
|
|
66
|
+
return deleted
|
|
67
|
+
|
|
68
|
+
return await session.run(operation_name="geometry_3d.clear_dimensions", operation=_operation)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Pure hexagonal-prism detection from exact planar-face facts — no KsAPI, no mesh.
|
|
2
|
+
|
|
3
|
+
`PlanarFaces` (from `features.geometry_3d.ksapi.component_geometry.component_planar_faces`)
|
|
4
|
+
already did the only KsAPI-touching work: found every planar face of a component whose
|
|
5
|
+
plane is parallel to the component's own axis, with an exact radial distance and exact
|
|
6
|
+
corner points (see that function's docstring — no tessellation anywhere in that path).
|
|
7
|
+
This module only clusters those already-computed facts — pure math, consumes DTOs, same
|
|
8
|
+
shape as `wrench_zone.py` (no pydantic-ai, no bridge port calls).
|
|
9
|
+
|
|
10
|
+
A hexagonal prism (a bolt head or a nut) presents as a GROUP of side-wall faces sharing
|
|
11
|
+
one radial distance from the axis (K = S/2, ГОСТ 13682-80) — a live check (2026-07-07)
|
|
12
|
+
found 6 for a plain nut and 12 for a bolt head (KOMPAS split each flat in two at the
|
|
13
|
+
under-head bearing chamfer, both halves at the identical radius) — hence "count is a
|
|
14
|
+
multiple of 6", not "count is exactly 6".
|
|
15
|
+
|
|
16
|
+
The z-zone this produces plugs directly into `measure_radial_distance`'s
|
|
17
|
+
`z_min_mm`/`z_max_mm` (same axis-projection convention, `axis_math.py`) — replacing
|
|
18
|
+
the LLM's hand-guessed zone that caused the false "Покемон mешает гайке" verdict this
|
|
19
|
+
task originates from (see AGENTS.md §«KsAPI: точный B-rep вместо меша/тесселляции»).
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from pydantic import Field
|
|
25
|
+
|
|
26
|
+
from kompas_kernel.features.geometry_3d.axis_math import axial_and_radial_mm, unit_axis_direction
|
|
27
|
+
from kompas_kernel.features.geometry_3d.models import AxisLine, PlanarFaces
|
|
28
|
+
from kompas_kernel.utils.validation import CustomModel
|
|
29
|
+
|
|
30
|
+
_HEX_FACE_COUNT_DIVISOR = 6
|
|
31
|
+
_DEFAULT_RADIUS_TOLERANCE_MM = 1e-2
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class HexPrismRegion(CustomModel):
|
|
35
|
+
"""One hexagonal-prism region found on a component's own axis, mm.
|
|
36
|
+
|
|
37
|
+
`z_min_mm`/`z_max_mm` — axial extent along the `AxisLine` passed to `find_hex_prisms`
|
|
38
|
+
(same convention `measure_radial_distance` expects for its own `z_min_mm`/`z_max_mm` —
|
|
39
|
+
a region's bounds plug straight in, no conversion). `across_flats_mm` — 2 × the
|
|
40
|
+
group's shared radial distance (= S per ГОСТ, measured from geometry, not looked up —
|
|
41
|
+
useful as a cross-check against `search_fastener`'s S). `face_indices` — which
|
|
42
|
+
`PlanarFaceFact.face_index` values formed this region (diagnostics/highlighting).
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
z_min_mm: float
|
|
46
|
+
z_max_mm: float
|
|
47
|
+
across_flats_mm: float = Field(gt=0)
|
|
48
|
+
face_indices: list[int]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def find_hex_prisms(
|
|
52
|
+
axis: AxisLine,
|
|
53
|
+
faces: PlanarFaces,
|
|
54
|
+
*,
|
|
55
|
+
radius_tolerance_mm: float = _DEFAULT_RADIUS_TOLERANCE_MM,
|
|
56
|
+
) -> list[HexPrismRegion]:
|
|
57
|
+
"""Group axis-parallel planar faces into hexagonal-prism regions, sorted by `z_min_mm`.
|
|
58
|
+
|
|
59
|
+
Grouping: two faces belong to the same region if their `radial_mm` (already computed
|
|
60
|
+
exactly by `component_planar_faces` — see its docstring) match within
|
|
61
|
+
`radius_tolerance_mm`. This is exact B-rep geometry, not a tessellation fit, so the
|
|
62
|
+
default tolerance (0.01 mm) only absorbs float noise, not modeling error — a real
|
|
63
|
+
hex flat's radius does not drift between faces.
|
|
64
|
+
|
|
65
|
+
A group is kept only if its face count is a positive multiple of 6 (a hexagon has 6
|
|
66
|
+
side walls; KOMPAS may split each flat into more than one topological face at a
|
|
67
|
+
chamfer/fillet transition, always in multiples of 6 for a regular hex — see module
|
|
68
|
+
docstring). Groups that don't fit (stray coplanar faces from unrelated features
|
|
69
|
+
landing at the same radius by coincidence) are silently dropped — a false NEGATIVE
|
|
70
|
+
(missing a real hex) is safer here than a false POSITIVE feeding a wrong z-zone into
|
|
71
|
+
`measure_radial_distance`.
|
|
72
|
+
|
|
73
|
+
Each kept group's `z_min_mm`/`z_max_mm` is the union of its member faces' corner
|
|
74
|
+
points projected onto `axis` (`axis_math.axial_and_radial_mm`) — the group's full
|
|
75
|
+
axial reach, not a single face's.
|
|
76
|
+
"""
|
|
77
|
+
unit = unit_axis_direction(axis)
|
|
78
|
+
axial_ranges: list[tuple[float, float]] = []
|
|
79
|
+
for fact in faces.faces:
|
|
80
|
+
axial_values = [axial_and_radial_mm(corner, axis, unit)[0] for corner in fact.corners]
|
|
81
|
+
if not axial_values:
|
|
82
|
+
axial_ranges.append((0.0, 0.0))
|
|
83
|
+
continue
|
|
84
|
+
axial_ranges.append((min(axial_values), max(axial_values)))
|
|
85
|
+
|
|
86
|
+
groups: list[list[int]] = [] # indices into faces.faces
|
|
87
|
+
for index, fact in enumerate(faces.faces):
|
|
88
|
+
placed = False
|
|
89
|
+
for group in groups:
|
|
90
|
+
if abs(faces.faces[group[0]].radial_mm - fact.radial_mm) <= radius_tolerance_mm:
|
|
91
|
+
group.append(index)
|
|
92
|
+
placed = True
|
|
93
|
+
break
|
|
94
|
+
if not placed:
|
|
95
|
+
groups.append([index])
|
|
96
|
+
|
|
97
|
+
regions: list[HexPrismRegion] = []
|
|
98
|
+
for group in groups:
|
|
99
|
+
if len(group) == 0 or len(group) % _HEX_FACE_COUNT_DIVISOR != 0:
|
|
100
|
+
continue
|
|
101
|
+
z_min_mm = min(axial_ranges[i][0] for i in group)
|
|
102
|
+
z_max_mm = max(axial_ranges[i][1] for i in group)
|
|
103
|
+
radial_mm = sum(faces.faces[i].radial_mm for i in group) / len(group)
|
|
104
|
+
regions.append(
|
|
105
|
+
HexPrismRegion(
|
|
106
|
+
z_min_mm=z_min_mm,
|
|
107
|
+
z_max_mm=z_max_mm,
|
|
108
|
+
across_flats_mm=2 * radial_mm,
|
|
109
|
+
face_indices=[faces.faces[i].face_index for i in group],
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
regions.sort(key=lambda region: region.z_min_mm)
|
|
113
|
+
return regions
|