Условные обозначения по электрике: библиотека блоков + описание примитивов
- library/электрика_блоки.dxf — 4 блока (СВ_ВСТР, СВ_БРА, РОЗ_2, ВЫКЛ_3) для вставки - symbols/ + preview/ — по файлу и картинке на символ - docs/примитивы-электрики.md — разбор по примитивам, атрибутам, слоям, порядок сборки через MCP, грабли - docs/условные-обозначения.md, conventions/*.json — легенда из эталона (правило: на лист не ставить) - docs/электрические-планы-ГОСТ.md — накопленные правила оформления - scripts/build_symbols_mcp.py (проверен на живом MCP 1.6.0-ours, 0 анонимных блоков), scripts/inspect_dxf.py - examples/plan_el_final.dxf/.pdf/.png — пример применения (14 вставок)
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
out/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# История изменений
|
||||||
|
|
||||||
|
## 05.10.2026 — оформление в репозиторий
|
||||||
|
- Библиотека символов выделена из рабочего плана: `library/электрика_блоки.dxf` (4 блока),
|
||||||
|
по одному файлу на символ в `symbols/`, PNG-превью в `preview/`.
|
||||||
|
- Написан `docs/примитивы-электрики.md` — разбор каждого символа по примитивам, атрибутам и слоям,
|
||||||
|
порядок сборки через MCP, проверки и грабли.
|
||||||
|
- Добавлен воспроизводимый скрипт сборки `scripts/build_symbols_mcp.py` и инвентаризация
|
||||||
|
`scripts/inspect_dxf.py`.
|
||||||
|
- В `docs/` перенесены накопленные правила: `электрические-планы-ГОСТ.md`,
|
||||||
|
`условные-обозначения.md` (+ машинный список в `conventions/`).
|
||||||
|
- Правило Павла зафиксировано: «условные обозначения» на лист не ставить — держать отдельным файлом.
|
||||||
|
|
||||||
|
## 01.10.2026 — сборка символов
|
||||||
|
- Собраны четыре символа как именованные блоки с атрибутами: `СВ_ВСТР`, `СВ_БРА`, `РОЗ_2`, `ВЫКЛ_3`
|
||||||
|
(примитивы `CIRCLE`/`ARC`/`LINE`, атрибуты `МАРКА`, `ТИП`, `ВЫСОТА`, `[НАЗНАЧ]`, `ГРУППА`/`ГРУППЫ`).
|
||||||
|
- Слои: `СО_СВЕТИЛЬНИКИ`, `СО_ВЫКЛЮЧАТЕЛИ`, `ЭО_РОЗЕТКИ`, `АР_ПОДЛОЖКА`, `ВЕДОМОСТЬ`, `РАЗМЕРЫ`.
|
||||||
|
- Проверено на живом AutoCAD 2023 (офисный ПК, `accoreconsole`): файл открывается, `rc=0`,
|
||||||
|
стиль `ГОСТ A` — `isocpeur.ttf`.
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Условные обозначения по электрике (AutoCAD) — библиотека и описание
|
||||||
|
|
||||||
|
Репозиторий содержит **наши рабочие условные обозначения для планов электрики** (освещение,
|
||||||
|
розетки, выключатели), собранные как блоки AutoCAD с атрибутами, и **описание того, как именно
|
||||||
|
эти примитивы сделаны** — по шагам, с точными размерами и вызовами MCP-сервера.
|
||||||
|
|
||||||
|
Сделано 01.10.2026, оформлено в репозиторий 05.10.2026. Автор — агент Hermes (Анатолий),
|
||||||
|
постановка — Павел (ИП Николашкин П.В.).
|
||||||
|
|
||||||
|
## Что внутри
|
||||||
|
|
||||||
|
| Папка / файл | Что это |
|
||||||
|
|---|---|
|
||||||
|
| `library/электрика_блоки.dxf` | **Все четыре символа одним файлом** — удобно вставить как библиотеку блоков |
|
||||||
|
| `symbols/СВ_ВСТР.dxf`, `СВ_БРА.dxf`, `РОЗ_2.dxf`, `ВЫКЛ_3.dxf` | По файлу на символ (в модели одна вставка блока) |
|
||||||
|
| `preview/*.png` | Картинки символов — посмотреть без AutoCAD |
|
||||||
|
| `docs/примитивы-электрики.md` | **Главный документ:** из каких примитивов собран каждый символ, какие атрибуты, слои, порядок вызовов MCP, проверки и грабли |
|
||||||
|
| `docs/условные-обозначения.md` | Легенда «Условные обозначения» из эталона Павла (текстовые подписи) + таблица наших символов |
|
||||||
|
| `docs/электрические-планы-ГОСТ.md` | Накопленные правила: слои, оформление, легенда, ловушки |
|
||||||
|
| `conventions/условные_обозначения.json` | Тот же список подписей в машинном виде (для подстановки в лист) |
|
||||||
|
| `examples/plan_el_final.dxf`, `.pdf`, `.png` | Пример плана, где эти символы применены (14 вставок) |
|
||||||
|
| `scripts/build_symbols_mcp.py` | Скрипт, который **собирает символы заново** через MCP-сервер AutoCAD (воспроизводимость) |
|
||||||
|
| `scripts/inspect_dxf.py` | Инвентаризация DXF: блоки, атрибуты, слои, вставки |
|
||||||
|
|
||||||
|
## Символы (кратко)
|
||||||
|
|
||||||
|
| Блок | Что обозначает | Примитивы | Атрибуты |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `СВ_ВСТР` | светильник встраиваемый | окружность R150 + две диагонали | МАРКА, ТИП, ВЫСОТА, ГРУППА |
|
||||||
|
| `СВ_БРА` | бра (настенный) | дуга R150 (0…180°) + линия-основание + стойка | МАРКА, ТИП, ВЫСОТА, ГРУППА |
|
||||||
|
| `РОЗ_2` | розетка двойная с з/к | дуга R150 + основание + стойка + перекладина | МАРКА, ТИП, ВЫСОТА, НАЗНАЧ, ГРУППА |
|
||||||
|
| `ВЫКЛ_3` | выключатель 3-клавишный | окружность R150 + стойка + перекладина | МАРКА, ТИП, ВЫСОТА, ГРУППЫ |
|
||||||
|
|
||||||
|
Все символы имеют базовую точку `(0,0)`, вставляются в масштабе плана (чертёжные единицы = мм
|
||||||
|
плана), маркируются через атрибуты — именно поэтому из них собирается ведомость.
|
||||||
|
|
||||||
|
## Как пользоваться
|
||||||
|
|
||||||
|
1. **Быстро:** открыть `library/электрика_блоки.dxf` и скопировать нужный блок в свой чертёж
|
||||||
|
(`Ctrl+Shift+C` → `Ctrl+Shift+V` в AutoCAD) либо подключить файл как библиотеку.
|
||||||
|
2. **По одному:** взять `symbols/<БЛОК>.dxf`.
|
||||||
|
3. **Программно (через агента):** `scripts/build_symbols_mcp.py` создаёт символы на MCP-сервере
|
||||||
|
AutoCAD (`autocad-mcp-pro`) — так же, как они были сделаны изначально; в конце печатает
|
||||||
|
проверку (список блоков, атрибуты, число вставок).
|
||||||
|
|
||||||
|
## Статус и оговорки
|
||||||
|
|
||||||
|
- Это **наши рабочие обозначения** для замаркировки планов освещения и розеточной сети.
|
||||||
|
Они не заявлены как точная копия приложения к конкретному ГОСТ/СП — при сдаче конкретного
|
||||||
|
проекта сверяйте форму знаков с заданием заказчика.
|
||||||
|
- Наследие: символы проектировались под план в масштабе **1:100** (размер знака 300×300 мм плана,
|
||||||
|
атрибуты — столбцом под знаком, как «замаркировка»).
|
||||||
|
- Правило Павла: **«условные обозначения» на сам лист не ставить** — держать отдельным файлом
|
||||||
|
и применять по необходимости (см. `docs/условные-обозначения.md`).
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "00 БЛОКИ АННОТАЦИЙ",
|
||||||
|
"стиль": "ОСНОВНОЙ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\C256;\\c0;ПРОЕКТ ###############################}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "00 БЛОКИ АННОТАЦИЙ",
|
||||||
|
"стиль": "ОСНОВНОЙ",
|
||||||
|
"высота": 2.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b1|i0|c204|p34;\\H1.25x;\\C256;\\c0;ИП Николашкин П.В.\\fISOCPEUR|b0|i0|c204|p34;\\"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.5,
|
||||||
|
"текст": "{\\fISOCPEUR|b1|i0|c204|p34;\\Q0;Условные обозначения}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Демонтированные стены и перегородки}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Вновь возведенные стены и перегородки}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Существующие стены и перегородки}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Устройство проемов в существующих стенах}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Заделка проемов}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Радиатор отопления}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"блок": "*Paper_Space",
|
||||||
|
"слой": "0",
|
||||||
|
"стиль": "ГОСТ",
|
||||||
|
"высота": 3.0,
|
||||||
|
"текст": "{\\fISOCPEUR|b0|i0|c204|p34;\\Q0;Вентиляционный канал}"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
# Что сделано с примитивами по электрике
|
||||||
|
|
||||||
|
Документ описывает, **из чего и как собраны** наши условные обозначения по электрике в AutoCAD:
|
||||||
|
каждый символ разобран по примитивам, указаны атрибуты, слои, последовательность вызовов
|
||||||
|
MCP-сервера и проверки. Дата работы: **01.10.2026**, оформлено 05.10.2026.
|
||||||
|
|
||||||
|
## 1. Общая схема
|
||||||
|
|
||||||
|
Символ = **блок AutoCAD**, собранный из простых примитивов (`CIRCLE`, `ARC`, `LINE`),
|
||||||
|
с **атрибутами (ATTDEF)**, которые несут маркировку. Такой блок:
|
||||||
|
|
||||||
|
- вставляется как единый объект (одна вставка `INSERT`, а не набор линий);
|
||||||
|
- несёт данные (марка, тип, высота, группа включения) — из них собирается ведомость;
|
||||||
|
- переиспользуется на всех планах, поэтому правка символа меняет все вставки.
|
||||||
|
|
||||||
|
Слои (по назначению):
|
||||||
|
|
||||||
|
| Слой | Что на нём |
|
||||||
|
|---|---|
|
||||||
|
| `СО_СВЕТИЛЬНИКИ` | символы освещения |
|
||||||
|
| `СО_ВЫКЛЮЧАТЕЛИ` | символы выключателей |
|
||||||
|
| `ЭО_РОЗЕТКИ` | символы розеток |
|
||||||
|
| `СО_ГРУППЫ` | подписи групп включения |
|
||||||
|
| `АР_ПОДЛОЖКА` | архитектурная подложка (стены, перегородки) |
|
||||||
|
| `ВЕДОМОСТЬ`, `РАЗМЕРЫ` | таблица и размеры |
|
||||||
|
| `00 БЛОКИ АННОТАЦИЙ` | подписи/выноски (стиль ОСНОВНОЙ, isocpeur) |
|
||||||
|
| `RAMKA`, `STAMPS` | рамка и основная надпись (форма 3) |
|
||||||
|
|
||||||
|
## 2. Разбор символов по примитивам
|
||||||
|
|
||||||
|
Все блоки имеют базовую точку `(0,0)`. Размеры — в единицах чертежа (мм плана).
|
||||||
|
|
||||||
|
### `СВ_ВСТР` — светильник встраиваемый (слой `СО_СВЕТИЛЬНИКИ`)
|
||||||
|
|
||||||
|
| Примитив | Параметры |
|
||||||
|
|---|---|
|
||||||
|
| `CIRCLE` | центр `(0,0)`, R = 150 |
|
||||||
|
| `LINE` | `(−106,−106) → (106,106)` |
|
||||||
|
| `LINE` | `(−106,106) → (106,−106)` |
|
||||||
|
|
||||||
|
Атрибуты (ATTDEF):
|
||||||
|
|
||||||
|
| Тег | Подсказка | Позиция | Высота | Значение по умолчанию |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `МАРКА` | Марка светильника | (−60, 200) | 120 | `Т1` |
|
||||||
|
| `ТИП` | Тип по спецификации | (−300, −320) | 90 | `встраиваемый` |
|
||||||
|
| `ВЫСОТА` | Высота от пола, мм | (−120, −450) | 90 | `0` |
|
||||||
|
| `ГРУППА` | Группа включения | (−60, 350) | 90 | `1.1` |
|
||||||
|
|
||||||
|
### `СВ_БРА` — бра (настенный светильник, слой `СО_СВЕТИЛЬНИКИ`)
|
||||||
|
|
||||||
|
| Примитив | Параметры |
|
||||||
|
|---|---|
|
||||||
|
| `ARC` | центр `(0,0)`, R = 150, углы 0°…180° |
|
||||||
|
| `LINE` | `(−150,0) → (150,0)` |
|
||||||
|
| `LINE` | `(0,0) → (0,−120)` |
|
||||||
|
|
||||||
|
Атрибуты: `МАРКА` (−60, 220) h120 = `Т10`; `ТИП` (−300, −350) h90 = `бра`;
|
||||||
|
`ВЫСОТА` (−120, −480) h90 = `1800`; `ГРУППА` (−60, 360) h90 = `1.1`.
|
||||||
|
|
||||||
|
### `РОЗ_2` — розетка двойная с заземляющим контактом (слой `ЭО_РОЗЕТКИ`)
|
||||||
|
|
||||||
|
| Примитив | Параметры |
|
||||||
|
|---|---|
|
||||||
|
| `ARC` | центр `(0,0)`, R = 150, углы 0°…180° |
|
||||||
|
| `LINE` | `(−150,0) → (150,0)` |
|
||||||
|
| `LINE` | `(0,0) → (0,200)` |
|
||||||
|
| `LINE` | `(−60,200) → (60,200)` |
|
||||||
|
|
||||||
|
Атрибуты (пять): `МАРКА` (−60, −250) h120 = `S1`; `ТИП` (−300, −380) h90 = `розетка двойная с з/к`;
|
||||||
|
`ВЫСОТА` (−120, −510) h90 = `300`; `НАЗНАЧ` (−150, −640) h90 = `общее`;
|
||||||
|
`ГРУППА` (−60, 260) h90 = `1.1`.
|
||||||
|
|
||||||
|
### `ВЫКЛ_3` — выключатель трёхклавишный (слой `СО_ВЫКЛЮЧАТЕЛИ`)
|
||||||
|
|
||||||
|
| Примитив | Параметры |
|
||||||
|
|---|---|
|
||||||
|
| `CIRCLE` | центр `(0,0)`, R = 150 |
|
||||||
|
| `LINE` | `(0,0) → (0,300)` |
|
||||||
|
| `LINE` | `(−100,300) → (100,300)` |
|
||||||
|
|
||||||
|
Атрибуты: `МАРКА` (−60, −250) h120 = `V1`; `ТИП` (−300, −380) h90 = `выключатель 3-клавишный`;
|
||||||
|
`ВЫСОТА` (−120, −510) h90 = `900`; `ГРУППЫ` (−200, −640) h90 = `1.1;1.2;1.3`.
|
||||||
|
|
||||||
|
> Замечание по подписям: атрибуты заданы **столбцом под знаком** (и группа — над знаком).
|
||||||
|
> Это осознанная схема «замаркировки» для плана 1:100: марка читается рядом со знаком,
|
||||||
|
> тип/высота/назначение — строкой ниже. Если для конкретного проекта нужна подпись в строчку
|
||||||
|
> или со стрелкой-выноской, координаты ATTDEF подстраиваются в блоке (правка блока меняет все вставки).
|
||||||
|
|
||||||
|
## 3. Порядок сборки через MCP-сервер (как это делалось)
|
||||||
|
|
||||||
|
Символы собраны не руками в AutoCAD, а командами MCP-сервера `autocad-mcp-pro`
|
||||||
|
(у нас: `10.26.5.108:30015` — рабочая сборка; `:30041` — сборка 1.6.0 с нашим патчем).
|
||||||
|
Последовательность для каждого символа:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. drawing_new — новый чертёж
|
||||||
|
2. layer_create name=<слой> — слой символа (CO_СВЕТИЛЬНИКИ / ЭО_РОЗЕТКИ / ...)
|
||||||
|
3. entity_create_circle / entity_create_arc / entity_create_line
|
||||||
|
— примитивы будущего знака (параметры из раздела 2)
|
||||||
|
4. block_create_from_entities
|
||||||
|
name=<БЛОК> handles=[...] base_x=0 base_y=0
|
||||||
|
— из примитивов делается ИМЕНОВАННЫЙ блок
|
||||||
|
5. entity_create_attdef block_name=<БЛОК> tag=МАРКА x=.. y=.. height=.. default=..
|
||||||
|
(по разу на каждый тег: МАРКА, ТИП, ВЫСОТА, [НАЗНАЧ], ГРУППА/ГРУППЫ)
|
||||||
|
6. block_insert name=<БЛОК> x=.. y=.. layer=<слой> attributes={"МАРКА":"Т1", "ТИП":"...", ...}
|
||||||
|
— вставки на плане, значения атрибутов подставляются
|
||||||
|
7. drawing_save_as / drawing_export_pdf — сохранение DXF/PDF
|
||||||
|
```
|
||||||
|
|
||||||
|
Готовый скрипт, повторяющий сборку: `scripts/build_symbols_mcp.py` (можно запускать на другом
|
||||||
|
чертеже/сервере, параметры символов вынесены в начало файла).
|
||||||
|
|
||||||
|
## 4. Проверки, которые выполнялись (и как повторить)
|
||||||
|
|
||||||
|
| Что проверяем | Команда MCP | Ожидаемый результат |
|
||||||
|
|---|---|---|
|
||||||
|
| Блоки именованные, а не анонимные | `block_list {"compact": true}` | в списке `СВ_ВСТР`, `СВ_БРА`, `РОЗ_2`, `ВЫКЛ_3`, нет `*U…` |
|
||||||
|
| Атрибуты у блока есть | `block_get_attdefs {"name": "<БЛОК>"}` | по 4–5 тегов на символ |
|
||||||
|
| Значения читаются обратно | `block_get_attributes {"handle": <вставка>}` | `{"МАРКА": "Т15", "ТИП": "светильник", …}` |
|
||||||
|
| Вставки на плане | `block_find_references {"name": "<БЛОК>"}` | 14 вставок на плане-примере |
|
||||||
|
| Файл валиден в AutoCAD | открытие в `accoreconsole` (офисный ПК) | `rc=0`, стиль `ГОСТ A` = `isocpeur.ttf` |
|
||||||
|
|
||||||
|
Локальная инвентаризация без AutoCAD: `scripts/inspect_dxf.py` (ezdxf).
|
||||||
|
|
||||||
|
## 5. Грабли (собраны на живых прогонах)
|
||||||
|
|
||||||
|
1. **Анонимные блоки `*U`. **Если собрать примитивы и не создать именованный блок, `block_insert`
|
||||||
|
вставляет `*U`-блок: он не переиспользуется, не имеет атрибутов и не попадает в ведомость.
|
||||||
|
Лечение: сначала `block_create_from_entities` с именем, только потом вставки. Проверять
|
||||||
|
`block_list` на отсутствие `*U`.
|
||||||
|
2. **ATTDEF до вставок.** Если объявить атрибуты после вставок, старые вставки остаются без
|
||||||
|
атрибутов (`block_get_attributes` вернёт `{}`).
|
||||||
|
3. **Отдельный файл — только удалением.** Когда нужно выделить из большого DXF один символ/зону,
|
||||||
|
нельзя собирать новый документ копированием: `MTEXT` ссылается на текстовый стиль, которого
|
||||||
|
в новом файле нет, и AutoCAD отвечает `rc=53 «неправильный или неполный DXF»`. Правильно —
|
||||||
|
открыть исходный файл и удалить лишнее (`e.destroy()`): таблицы стилей, слоёв и блоков остаются.
|
||||||
|
Тот же приём спас при сборке этого репозитория: при удалении блока-стрелки `_ARCHTICK`
|
||||||
|
размерные стили ссылаются на несуществующий блок и файл не сохраняется — блоки с именами
|
||||||
|
на `_` (стрелки и маркеры размеров) удалять нельзя.
|
||||||
|
4. **PDF: формат листа.** Раньше PDF «подгонялся» по содержимому и A3 превращался в 167×122 мм.
|
||||||
|
В нашей сборке лист задаётся явно и проверяется медиабокс: A3 = **420×297 мм** (допуск ±2).
|
||||||
|
5. **Текст в PDF.** Для читаемого PDF нужен настоящий текстовый слой (инлайн-кодировка шрифта)
|
||||||
|
— иначе в PDF остаются кривые и текст не ищется/не копируется.
|
||||||
|
6. **Легенду на лист не ставить.** Прямое правило Павла: «условные обозначения» выносить
|
||||||
|
отдельным файлом (`docs/условные-обозначения.md`), на листе не держать.
|
||||||
|
7. **Штриховка/подложка.** Архитектурная подложка — отдельный слой (`АР_ПОДЛОЖКА`), её видимость
|
||||||
|
регулируется, чтобы знаки читались.
|
||||||
|
|
||||||
|
## 6. Что можно улучшить (следующие шаги)
|
||||||
|
|
||||||
|
- Привести подписи к варианту «в строчку» со выноской, если так принято в проекте заказчика.
|
||||||
|
- Добавить растровые превью в сами DXF (эскиз блока) для палитры AutoCAD.
|
||||||
|
- Расширить набор: светильники (подвесной, бра, точечный), розетки (1/2/3-местные, IP), выключатели
|
||||||
|
(1/2/3-клавишные, проходные), щиты, датчики — та же схема (примитивы + ATTDEF + слои).
|
||||||
|
- Собрать из этих блоков ведомость автоматически (по атрибутам `МАРКА`/`ТИП`/`ГРУППА`).
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Условные обозначения (вынесены из образца отдельно)
|
||||||
|
|
||||||
|
В лист не добавляются — применять по необходимости отдельным блоком справа от плана.
|
||||||
|
|
||||||
|
Все подписи — стиль isocpeur, высота 3 мм, с инлайновым кодом шрифта.
|
||||||
|
|
||||||
|
| № | Текст обозначения |
|
||||||
|
|---|---|
|
||||||
|
| 1 | {\C256;\c0;ПРОЕКТ ###############################} |
|
||||||
|
| 2 | {\fISOCPEUR|b1|i0|c204|p34;\H1.25x;\C256;\c0;ИП Николашкин П.В.\fISOCPEUR|b0|i0|c204|p34;\ |
|
||||||
|
| 3 | {\fISOCPEUR|b1|i0|c204|p34;\Q0;Условные обозначения} |
|
||||||
|
| 4 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Демонтированные стены и перегородки} |
|
||||||
|
| 5 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Вновь возведенные стены и перегородки} |
|
||||||
|
| 6 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Существующие стены и перегородки} |
|
||||||
|
| 7 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Устройство проемов в существующих стенах} |
|
||||||
|
| 8 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Заделка проемов} |
|
||||||
|
| 9 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Радиатор отопления} |
|
||||||
|
| 10 | {\fISOCPEUR|b0|i0|c204|p34;\Q0;Вентиляционный канал} |
|
||||||
|
|
||||||
|
Машинная версия: `условные_обозначения.json`.
|
||||||
|
В образце раздел стоит справа от плана; графические образцы линий — в блоке `A$C5672f958`.
|
||||||
|
Дополнительно в скилле: `образец_листа_форма3.md`, `шаблон_листа_форма3.json`, `образец_листа.dxf`.
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Комплект чертежей по ГОСТ из данных — а не «картинкой от нейросети»
|
||||||
|
|
||||||
|
Класс задач: «получить комплект планов (электрика, полы, потолки, демонтаж) уровня рабочей документации, сгенерированный автоматически». Собран 01.10.2026 по поводу ролика Михаила Жилина (дизайнер интерьера, ТОП-100 AD) — «Я попросил GPT-6 Astra нарисовать чертежи электрики квартиры 100 м²» (https://www.youtube.com/watch?v=Sto1bDtOlY8, 26.09.2026, 15:18, 14 439 просмотров).
|
||||||
|
|
||||||
|
## 1. Что именно показал ролик (референс «планки качества»)
|
||||||
|
|
||||||
|
Автор дал модели 4 исходника: 2D-планировку, свою же 3D-модель, комплект визуализаций и **пример рабочей документации как образец**. Получил **4 согласованных листа по электрике за ≈35 минут** (первые два — 9 мин 42 сек, вторые два — 27 мин).
|
||||||
|
|
||||||
|
| № | Лист | Содержание |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | План расстановки светового оборудования | световые точки с привязками + ведомость световых точек |
|
||||||
|
| 2 | План маркировки светового оборудования | спецификация типов светильников (споты, треки, бра, настольные лампы) |
|
||||||
|
| 3 | План выключателей и групп включения света | мастер-кнопка при входе + группы по зонам (обозначения V03) |
|
||||||
|
| 4 | План расстановки электрического оборудования | розетки, выводы под технику, ТВ, интернет (S40), драйверы (E08) |
|
||||||
|
|
||||||
|
**Приёмы, которые стоит забирать (работают и без всякой Astra):**
|
||||||
|
1. **«Сделай по образцу»** — дать пример готовой РД, а не описывать словами. Это то, что дало состав и оформление листов.
|
||||||
|
2. **Опираться на промежуточный наглядный артефакт** — модель «прочитала» свои же визуализации и расставила точки по ним. Аналог у нас: сначала растровая подложка/эскиз, потом координаты.
|
||||||
|
3. **Комплект, а не один лист.** Ценность — в наборе из 4 согласованных листов (расстановка → маркировка → группы → розетки).
|
||||||
|
|
||||||
|
**Косяки, которые у него остались (ровно то, что в AutoCAD ловится кодом):** светильники «съехали» с оси в 2 местах; высота бра на листе (1 800) не бьётся с визуализацией; выключатель поставлен в угол вместо фартука; **розетка над варочной поверхностью — лишняя**; выключатели не размечены по расстоянию от проёма.
|
||||||
|
|
||||||
|
**Экономика по словам автора:** 35 минут и подписка $20/мес против 2 недель работы дизайнера студии и более 100 000 ₽. Год назад на этой задаче было «полный мрак».
|
||||||
|
|
||||||
|
**Ключевое допущение (не цитата автора — вывод из ролика):** DWG, слои, блоки и сохранённый файл в ролике не упоминаются ни разу; единственный способ правки — «попросить его в чате исправить». То есть листы — это **растровые сгенерированные изображения**, а не рабочая документация в открытом формате. Отсюда и весь разрыв с AutoCAD-подходом: у нас на выходе редактируемый DWG со слоями и блоками, где символ перетаскивается мышкой и атрибут правится в свойствах.
|
||||||
|
|
||||||
|
## 2. Норматив (что брать за основу символов и оформления)
|
||||||
|
|
||||||
|
| Документ | Что даёт | Ссылка |
|
||||||
|
|---|---|---|
|
||||||
|
| **ГОСТ 21.210-2014** «СПДС. Условные графические изображения электрооборудования и проводок на планах» | таблицы изображений выключателей, переключателей, штепсельных розеток **с размерами в мм** — источник символов | docs.cntd.ru/document/1200115052 |
|
||||||
|
| **ГОСТ 21.614-88** | заменён 21.210-2014 — применять новый | ruscable.ru/info/snip/Data1/3/3117/index.htm |
|
||||||
|
| **ГОСТ Р 21.1101-2013** СПДС | основная надпись **форма 3** (и 5, 6), оформление листов | mt-r.ru/upload/blok-skhemy/GOST_Р_21_1101-2013_SPDS.pdf |
|
||||||
|
| **ГОСТ Р 21.101-2020** | актуальная редакция СПДС вместо 21.1101-2013 | fkr-spb.ru (PDF) |
|
||||||
|
|
||||||
|
⚠️ **ГОСТ ≠ ISO.** Встроенный в MCP `titleblock_apply_iso_a3` — это **ISO 7200**, другая таблица. Для РФ нужен свой блок рамки со штампом по форме 3.
|
||||||
|
|
||||||
|
## 3. Пять технологий AutoCAD, которые дают результат
|
||||||
|
|
||||||
|
1. **Блоки с атрибутами** (`BLOCK`/`ATTDEF`/`INSERT`). Символ розетки — одна сущность с полями тип/высота/группа/монтаж. Для параметрики — **динамические блоки** (набор видимости: одинарная/двойная/скрытая). Через наш MCP — `block_insert` с `attributes`.
|
||||||
|
2. **Извлечение данных** `DATAEXTRACTION` → нативная таблица прямо в чертеже + выгрузка в Excel/CSV. Ведомость **всегда сходится с чертежом**, потому что считается из него. Документация Autodesk: help.autodesk.com, справка AutoCAD 2025 (`GUID-D1433C93…`). В ezdxf-мире аналог — обход `INSERT` и `entity_create_table`.
|
||||||
|
3. **Слои и стили.** Нужны свои: `СПДС-СО.Светильники`, `СПДС-СО.Выключатели`, `СПДС-ЭО.Розетки`, `СПДС-ЭО.Группы`, `АР.Подложка-мебель`, `Штамп`, `Размеры`. Встроенный `template_apply_layers(electrical)` (7 слоёв, IEC-логика под схемы) для этого **не годится**.
|
||||||
|
4. **Лист:** Layout + Viewport + рамка со штампом; модель чертится 1:1, масштаб задаётся видовому экрану (`viewport_create(scale=1/50)`).
|
||||||
|
5. **Preflight кодом** вместо «глаза проверяющего»: розетка в зоне варочной/мойки → ошибка; у каждого символа заполнены обязательные атрибуты; количество символов типа == строка ведомости; светильники одной группы на одной оси; нет символов «на слое 0».
|
||||||
|
|
||||||
|
**Мелочь, дающая «то самое» ощущение чертежа:** подложка мебели приглушённым цветом (ACI 250/8) на отдельном слое + порядок отрисовки.
|
||||||
|
|
||||||
|
## 4. Готовые решения (проверено 01.10.2026)
|
||||||
|
|
||||||
|
| Решение | Что даёт | Статус |
|
||||||
|
|---|---|---|
|
||||||
|
| **U-C4N/Autocad-MCP** (`autocad-mcp-pro`) | наш текущий сервер, 149 инструментов: блоки с атрибутами, нативные таблицы, листы, HATCH, размеры, preflight, `system_run_lisp` | 113★ / 34 форка / обновлён 24.09.2026 / MIT |
|
||||||
|
| **Igualguana/AUTOCAD-ELECTRICAL-MCP** | MCP прямо под AutoCAD Electrical: 46 инструментов — electrical (7), wires (5), components (6), reports (5), project (6); COM, нужен живой AutoCAD | 16★ / 1 форк / 15.04.2026 / AGPL-3.0 |
|
||||||
|
| **harrissohail6/AutoCAD-Automation-Scripts** | ezdxf-скрипты ровно под эту задачу: `block_inserter` (вставка символов по CSV координат), `bom_generator` (спецификация из блоков в Excel), `layer_manager`, `cable_schedule`, `title_block_updater`, `symbol_library`. **Брать как образец вместо написания с нуля** | 3★ / 1 форк / 05.12.2025 / MIT |
|
||||||
|
| **dell4valt/gost_template** | рамки и основные надписи по ГОСТ Р 21.1101-2013 (формы 3, 5, 6, титульные листы), PDF/PNG/SVG/Visio, шрифт ISOCPEUR | 25★ / 7 форков / 2020 / без лицензии |
|
||||||
|
| **dwg.ru/dnl/15570** | динамический блок рамки со штампами уже по **ГОСТ Р 21.101-2020** (актуальнее, чем 21.1101-2013) | dwg.ru |
|
||||||
|
| **severin.su** | шаблон ГОСТ Р 21.1101-2013 под AutoCAD: формы 3/4/5/6, масштаб А4–А0×3, атрибуты из подшивки | severin.su |
|
||||||
|
| **AutoCAD Electrical (toolset)** | автонумерация проводов, генерация обозначений компонентов, автоматические отчёты и спецификации. По блогу Hagerman (27.04.2026) отчёты/BOM **на 97% быстрее**, чем в чистом AutoCAD. Входит в подписку AutoCAD 2027 — **стоит проверять, установлен ли toolset в AutoCAD 2023 RU на офисном ПК** | Autodesk |
|
||||||
|
| **Zoo Text-to-CAD** | пример правильного подхода «текст → CAD»: на выходе редактируемые параметрические модели, а не картинки | для сравнения подходов |
|
||||||
|
|
||||||
|
## 5. Пайплайн: 5 слоёв
|
||||||
|
|
||||||
|
```
|
||||||
|
Слой 1 Библиотека символов по ГОСТ 21.210-2014 (разово)
|
||||||
|
один DXF с блоками + ATTDEF: ТИП, ВЫСОТА, ГРУППА, МОНТАЖ, ПРИМЕЧАНИЕ
|
||||||
|
↓
|
||||||
|
Слой 2 Модель данных объекта (JSON): rooms[], lights[], sockets[], switches[]
|
||||||
|
— НЕ «координаты линий», а описание объекта с привязками и группами
|
||||||
|
↓
|
||||||
|
Слой 3 Скрипт-сборщик (детерминированный, без участия LLM на этом шаге)
|
||||||
|
ГОСТ-слои → block_insert(+attributes) → dimension_* → таблица-ведомость
|
||||||
|
(строки считает КОД) → layout_create + viewport_create + свой ГОСТ-штамп
|
||||||
|
→ drawing_export_dxf / drawing_export_pdf
|
||||||
|
↓
|
||||||
|
Слой 4 Preflight-проверки (drawing_preflight + свои правила, см. §3.5)
|
||||||
|
↓
|
||||||
|
Слой 5 Живой AutoCAD на Windows-ПК: динамические блоки, .dwt, подшивка .dst
|
||||||
|
(ezdxf это не умеет) — через COM + system_run_lisp
|
||||||
|
```
|
||||||
|
|
||||||
|
Пример JSON-модели:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"object": "квартира 100 м2",
|
||||||
|
"rooms": [{"id": "R1", "name": "Кухня-гостиная", "poly": [[0,0],[6.2,0],[6.2,7.4],[0,7.4]]}],
|
||||||
|
"lights": [{"block": "LIGHT_SPOT", "room": "R1", "x": 1.2, "y": 1.4, "h": 0, "group": "3.1"},
|
||||||
|
{"block": "LIGHT_PENDANT","room": "R1", "x": 3.1, "y": 5.6, "h": 0, "group": "3.3"}],
|
||||||
|
"sockets": [{"block": "SOCK_DOUBLE", "x": 0.15, "y": 1.10, "h": 1100, "use": "фартук"}],
|
||||||
|
"switches":[{"block": "SWITCH_3G", "x": 6.05, "y": 1.05, "h": 900,
|
||||||
|
"groups": ["3.1","3.2","3.3"]}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Группа включения обязана быть АТРИБУТОМ, а не текстом.** Иначе не построить ни схему групп, ни автопроверку по зонам.
|
||||||
|
|
||||||
|
## 6. План внедрения (3 этапа — предлагать Павлу именно так)
|
||||||
|
|
||||||
|
| Этап | Что делаем | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| 1. Библиотека + один лист | библиотека символов по ГОСТ 21.210-2014 с атрибутами; сборщик строит **один план расстановки света** из JSON блоками вместо линий | DXF/DWG с блоками, высотами, подложкой мебели |
|
||||||
|
| 2. Ведомость и комплект | авто-ведомость из атрибутов + листы «маркировка», «выключатели и группы», «розетки»; рамка и штамп форма 3 | тот же комплект из 4 листов, но редактируемый |
|
||||||
|
| 3. Preflight и приёмка | правила проверок + приёмка на живом объекте | комплект без вычитки вручную |
|
||||||
|
|
||||||
|
## 7. Риски и ограничения (проговаривать честно)
|
||||||
|
|
||||||
|
- Библиотеку символов **нельзя сгенерировать «на глаз»** — она должна быть по ГОСТ 21.210-2014, иначе чертёж не примут. Это ручная работа один раз.
|
||||||
|
- **Локальная модель (qwen3.8) не пишет длинный код** (проверено 18.08.2026: `finish_reason='length'`, зацикливание). Расстановку планирует модель, а строит **готовый скрипт**.
|
||||||
|
- `system_run_lisp` работает только на COM-бэкенде, т.е. при живом AutoCAD на Windows (`192.168.50.91`, AutoCAD 2023 RU) — из Docker недоступно.
|
||||||
|
- ezdxf не создаёт динамические блоки с параметрами и не работает с подшивкой `.dst`.
|
||||||
|
- Штамп: ISO 7200 ≠ ГОСТ Р 21.1101 — встроенный инструмент MCP здесь не подойдёт.
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,194 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Сборка условных обозначений по электрике через MCP-сервер AutoCAD.
|
||||||
|
|
||||||
|
Повторяет то, что было сделано 01.10.2026: каждый символ собирается из простых
|
||||||
|
примитивов в ИМЕНОВАННЫЙ блок с атрибутами (ATTDEF), затем вставляется на чертёж
|
||||||
|
и сохраняется в DXF.
|
||||||
|
|
||||||
|
Запуск:
|
||||||
|
python3 build_symbols_mcp.py --port 30041 --out ./out
|
||||||
|
(токен берётся из /opt/data/.autocad_mcp_token, либо из переменной ACAD_MCP_TOKEN)
|
||||||
|
|
||||||
|
Проверка после сборки — командой inspect_dxf.py или block_list/block_get_attributes.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import base64
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
# --- Описание символов: примитивы и атрибуты (единицы чертежа = мм плана) -------
|
||||||
|
SYMBOLS = {
|
||||||
|
"СВ_ВСТР": {
|
||||||
|
"layer": "СО_СВЕТИЛЬНИКИ",
|
||||||
|
"primitives": [
|
||||||
|
("entity_create_circle", {"cx": 0, "cy": 0, "radius": 150}),
|
||||||
|
("entity_create_line", {"x1": -106, "y1": -106, "x2": 106, "y2": 106}),
|
||||||
|
("entity_create_line", {"x1": -106, "y1": 106, "x2": 106, "y2": -106}),
|
||||||
|
],
|
||||||
|
"attdefs": [
|
||||||
|
("МАРКА", "Марка светильника", -60, 200, 120, "Т1"),
|
||||||
|
("ТИП", "Тип по спецификации", -300, -320, 90, "встраиваемый"),
|
||||||
|
("ВЫСОТА", "Высота от пола, мм", -120, -450, 90, "0"),
|
||||||
|
("ГРУППА", "Группа включения", -60, 350, 90, "1.1"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"СВ_БРА": {
|
||||||
|
"layer": "СО_СВЕТИЛЬНИКИ",
|
||||||
|
"primitives": [
|
||||||
|
("entity_create_arc", {"cx": 0, "cy": 0, "radius": 150, "start_angle": 0, "end_angle": 180}),
|
||||||
|
("entity_create_line", {"x1": -150, "y1": 0, "x2": 150, "y2": 0}),
|
||||||
|
("entity_create_line", {"x1": 0, "y1": 0, "x2": 0, "y2": -120}),
|
||||||
|
],
|
||||||
|
"attdefs": [
|
||||||
|
("МАРКА", "Марка светильника", -60, 220, 120, "Т10"),
|
||||||
|
("ТИП", "Тип по спецификации", -300, -350, 90, "бра"),
|
||||||
|
("ВЫСОТА", "Высота от пола, мм", -120, -480, 90, "1800"),
|
||||||
|
("ГРУППА", "Группа включения", -60, 360, 90, "1.1"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"РОЗ_2": {
|
||||||
|
"layer": "ЭО_РОЗЕТКИ",
|
||||||
|
"primitives": [
|
||||||
|
("entity_create_arc", {"cx": 0, "cy": 0, "radius": 150, "start_angle": 0, "end_angle": 180}),
|
||||||
|
("entity_create_line", {"x1": -150, "y1": 0, "x2": 150, "y2": 0}),
|
||||||
|
("entity_create_line", {"x1": 0, "y1": 0, "x2": 0, "y2": 200}),
|
||||||
|
("entity_create_line", {"x1": -60, "y1": 200, "x2": 60, "y2": 200}),
|
||||||
|
],
|
||||||
|
"attdefs": [
|
||||||
|
("МАРКА", "Марка розетки", -60, -250, 120, "S1"),
|
||||||
|
("ТИП", "Тип", -300, -380, 90, "розетка двойная с з/к"),
|
||||||
|
("ВЫСОТА", "Высота от пола, мм", -120, -510, 90, "300"),
|
||||||
|
("НАЗНАЧ", "Назначение", -150, -640, 90, "общее"),
|
||||||
|
("ГРУППА", "Группа", -60, 260, 90, "1.1"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ВЫКЛ_3": {
|
||||||
|
"layer": "СО_ВЫКЛЮЧАТЕЛИ",
|
||||||
|
"primitives": [
|
||||||
|
("entity_create_circle", {"cx": 0, "cy": 0, "radius": 150}),
|
||||||
|
("entity_create_line", {"x1": 0, "y1": 0, "x2": 0, "y2": 300}),
|
||||||
|
("entity_create_line", {"x1": -100, "y1": 300, "x2": 100, "y2": 300}),
|
||||||
|
],
|
||||||
|
"attdefs": [
|
||||||
|
("МАРКА", "Марка выключателя", -60, -250, 120, "V1"),
|
||||||
|
("ТИП", "Тип", -300, -380, 90, "выключатель 3-клавишный"),
|
||||||
|
("ВЫСОТА", "Высота от пола, мм", -120, -510, 90, "900"),
|
||||||
|
("ГРУППЫ", "Группы включения", -200, -640, 90, "1.1;1.2;1.3"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
INSERTS = [("СВ_ВСТР", 1200, 900, "Т1"), ("СВ_ВСТР", 3000, 900, "Т2"),
|
||||||
|
("ВЫКЛ_3", 1800, 0, "V1"), ("РОЗ_2", 3600, 0, "S1")]
|
||||||
|
|
||||||
|
|
||||||
|
class Mcp:
|
||||||
|
def __init__(self, port: str, token: str):
|
||||||
|
self.url = f"http://10.26.5.108:{port}/mcp"
|
||||||
|
self.token = token
|
||||||
|
self.sid = None
|
||||||
|
self._id = 0
|
||||||
|
|
||||||
|
def _rpc(self, payload):
|
||||||
|
headers = {"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json, text/event-stream",
|
||||||
|
"Authorization": f"Bearer {self.token}"}
|
||||||
|
if self.sid:
|
||||||
|
headers["Mcp-Session-Id"] = self.sid
|
||||||
|
req = urllib.request.Request(self.url, data=json.dumps(payload).encode(),
|
||||||
|
headers=headers, method="POST")
|
||||||
|
with urllib.request.urlopen(req, timeout=300) as r:
|
||||||
|
self.sid = r.headers.get("Mcp-Session-Id") or self.sid
|
||||||
|
raw = r.read().decode("utf-8", "replace")
|
||||||
|
msgs = []
|
||||||
|
for line in raw.splitlines():
|
||||||
|
if line.strip().startswith("data:"):
|
||||||
|
try:
|
||||||
|
msgs.append(json.loads(line[5:].strip()))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if not msgs:
|
||||||
|
try:
|
||||||
|
msgs = [json.loads(raw)]
|
||||||
|
except Exception:
|
||||||
|
msgs = []
|
||||||
|
for m in msgs:
|
||||||
|
if m.get("id") == payload.get("id"):
|
||||||
|
return m
|
||||||
|
return msgs[-1] if msgs else {}
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
m = self._rpc({"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
||||||
|
"params": {"protocolVersion": "2025-06-18", "capabilities": {},
|
||||||
|
"clientInfo": {"name": "build_symbols", "version": "1"}}})
|
||||||
|
self._rpc({"jsonrpc": "2.0", "method": "notifications/initialized"})
|
||||||
|
return ((m.get("result") or {}).get("serverInfo") or {})
|
||||||
|
|
||||||
|
def call(self, name, args=None):
|
||||||
|
self._id += 1
|
||||||
|
res = self._rpc({"jsonrpc": "2.0", "id": 1000 + self._id, "method": "tools/call",
|
||||||
|
"params": {"name": name, "arguments": args or {}}})
|
||||||
|
out = res.get("result") or {}
|
||||||
|
if res.get("error") or out.get("isError"):
|
||||||
|
raise RuntimeError(f"{name}: {str(res.get('error') or out)[:300]}")
|
||||||
|
return out.get("structuredContent") or out
|
||||||
|
|
||||||
|
|
||||||
|
def build(mcp: Mcp, out_dir: str):
|
||||||
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
mcp.call("drawing_new")
|
||||||
|
for layer, color in [("СО_СВЕТИЛЬНИКИ", 3), ("СО_ВЫКЛЮЧАТЕЛИ", 4), ("ЭО_РОЗЕТКИ", 5)]:
|
||||||
|
try:
|
||||||
|
mcp.call("layer_create", {"name": layer, "color": color})
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(f" слой {layer}: {e}")
|
||||||
|
|
||||||
|
for name, spec in SYMBOLS.items():
|
||||||
|
handles = []
|
||||||
|
for tool, args in spec["primitives"]:
|
||||||
|
r = mcp.call(tool, {**args, "layer": spec["layer"]})
|
||||||
|
h = r.get("handle")
|
||||||
|
if h:
|
||||||
|
handles.append(h)
|
||||||
|
mcp.call("block_create_from_entities",
|
||||||
|
{"name": name, "handles": handles, "base_x": 0, "base_y": 0})
|
||||||
|
for tag, prompt, x, y, height, default in spec["attdefs"]:
|
||||||
|
mcp.call("entity_create_attdef", {"block_name": name, "tag": tag, "prompt": prompt,
|
||||||
|
"x": x, "y": y, "height": height, "default": default})
|
||||||
|
print(f" блок {name}: примитивов {len(handles)}, атрибутов {len(spec['attdefs'])}")
|
||||||
|
|
||||||
|
for name, x, y, mark in INSERTS:
|
||||||
|
attrs = {"МАРКА": mark, "ТИП": SYMBOLS[name]["attdefs"][1][5],
|
||||||
|
"ВЫСОТА": SYMBOLS[name]["attdefs"][2][5], "ГРУППА": "1.1"}
|
||||||
|
mcp.call("block_insert", {"name": name, "x": x, "y": y,
|
||||||
|
"layer": SYMBOLS[name]["layer"], "attributes": attrs})
|
||||||
|
print(f" вставок на чертёж: {len(INSERTS)}")
|
||||||
|
|
||||||
|
dxf_in_container = "/opt/data/dxf/электрика_блоки.dxf"
|
||||||
|
mcp.call("drawing_save_as", {"path": dxf_in_container})
|
||||||
|
got = mcp.call("file_get", {"path": dxf_in_container})
|
||||||
|
data = got.get("content_base64") or ""
|
||||||
|
dst = os.path.join(out_dir, "электрика_блоки.dxf")
|
||||||
|
if data:
|
||||||
|
open(dst, "wb").write(base64.b64decode(data))
|
||||||
|
print(f" сохранено: {dst} ({os.path.getsize(dst)} байт)")
|
||||||
|
|
||||||
|
blocks = mcp.call("block_list", {"compact": True, "fields": ["name", "attribute_count"]})
|
||||||
|
print(" проверка block_list:", json.dumps(blocks.get("result", {}) or blocks, ensure_ascii=False)[:300])
|
||||||
|
anon = [r for r in (blocks.get("result", {}).get("rows") or []) if str(r[0]).startswith("*U")]
|
||||||
|
print(" анонимных блоков *U:", len(anon))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--port", default="30041", help="порт MCP-сервера AutoCAD (30015 — прод, 30041 — 1.6.0-ours)")
|
||||||
|
ap.add_argument("--out", default="./out")
|
||||||
|
a = ap.parse_args()
|
||||||
|
token = os.environ.get("ACAD_MCP_TOKEN") or open("/opt/data/.autocad_mcp_token", encoding="utf-8").read().strip()
|
||||||
|
m = Mcp(a.port, token)
|
||||||
|
print("сервер:", m.init().get("version"))
|
||||||
|
build(m, a.out)
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Инвентаризация DXF: блоки, атрибуты, слои, вставки. Без AutoCAD (ezdxf).
|
||||||
|
|
||||||
|
python3 inspect_dxf.py library/электрика_блоки.dxf
|
||||||
|
python3 inspect_dxf.py examples/plan_el_final.dxf
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import ezdxf
|
||||||
|
|
||||||
|
|
||||||
|
def inspect(path: str) -> None:
|
||||||
|
doc = ezdxf.readfile(path)
|
||||||
|
print(f"=== {path}")
|
||||||
|
print(f" версия DXF: {doc.dxfversion}")
|
||||||
|
print(f" слои ({len(doc.layers)}): {[l.dxf.name for l in doc.layers]}")
|
||||||
|
blocks = [b for b in doc.blocks if not b.name.startswith(("*Model", "*Paper"))]
|
||||||
|
print(f" блоков: {len(blocks)}")
|
||||||
|
for b in blocks:
|
||||||
|
kinds = {}
|
||||||
|
attdefs = []
|
||||||
|
for e in b:
|
||||||
|
kinds[e.dxftype()] = kinds.get(e.dxftype(), 0) + 1
|
||||||
|
if e.dxftype() == "ATTDEF":
|
||||||
|
attdefs.append(e.dxf.tag)
|
||||||
|
marker = " (служебный: стрелка/маркер размера)" if b.name.startswith("_") else ""
|
||||||
|
print(f" {b.name:<12} {kinds}{' атрибуты: ' + str(attdefs) if attdefs else ''}{marker}")
|
||||||
|
ins_model = [e for e in doc.modelspace() if e.dxftype() == "INSERT"]
|
||||||
|
print(f" вставок в модели: {len(ins_model)}")
|
||||||
|
for lay in doc.layouts:
|
||||||
|
if lay.name == "Model":
|
||||||
|
continue
|
||||||
|
n = sum(1 for e in lay if e.dxftype() == "INSERT")
|
||||||
|
if n:
|
||||||
|
print(f" вставок на листе «{lay.name}»: {n}")
|
||||||
|
bad = [b.name for b in blocks if b.name.startswith("*U")]
|
||||||
|
print(f" анонимных блоков *U: {len(bad)} {bad if bad else ''}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(1)
|
||||||
|
for p in sys.argv[1:]:
|
||||||
|
inspect(p)
|
||||||
+8116
File diff suppressed because it is too large
Load Diff
+8482
File diff suppressed because it is too large
Load Diff
+8122
File diff suppressed because it is too large
Load Diff
+8116
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user