Meridian Draw — спецификация приложения
Документ приложения по разделу 8 библии (
docs/00-foundation.md). Версия 0.1 · 2026-10-03. Собственный формат:.mvx(шаблон.mvt, плоский XML.mvxf), пространство имёнurn:meridian:office:draw:1, MIMEapplication/vnd.meridian.draw. Цвет приложения--app-draw#0E8A8A, значок — узел-коннектор. Крейты ядра:kernel/crates/meridian-draw(документ: страницы, слои, трафареты, данные фигур),meridian-scene(общая графика сцены: фигуры, геометрияprstGeom/custGeom, стили, группы, текст в фигурах — делится со Slides/Write/Sheets),meridian-route(маршрутизация коннекторов),meridian-graph-layout(Sugiyama, деревья, круговая, радиальная, силовая),meridian-geom(булевы операции, упрощение, подгонка кривых, hit-testing; обёртка надkurbo),meridian-chart,meridian-codecs-{vsdx,vsd,svg,dxf,drawio,emf,odf}; оболочка —shell/src/draw/(QML/C++); скрипты —meridian-script. Фаза по библии: 3 (12–22 мес от старта, вместе со Slides). Редакция:Feature::AppDraw(Home+); в Free документы Draw открываются на просмотр, печать и экспорт в PDF (см. §11);Feature::DrawVsdxExportиFeature::DrawStencilsPro— Pro.
Содержание
- Назначение и аналоги
- Функции (по группам, P0/P1/P2)
- Экраны
- Модель данных
- Алгоритмы
- MeridianScript API для Draw
- Форматы
- Горячие клавиши
- Критерии готовности 1.0
- Риски
- Вопросы к библии
1. Назначение и аналоги
Meridian Draw — редактор векторной графики и схем: блок-схемы, UML/BPMN, организационные диаграммы, сетевые и электрические схемы, планы помещений, mind map, а также свободная векторная графика (кривые Безье, булевы операции, текст по пути). Главное отличие от «рисовалок» — коннекторы с автомаршрутизацией, трафареты с параметрическими фигурами и данные фигур, связанные с таблицами.
1.1 Аналоги
| Продукт | Сильные стороны | Слабые стороны, которые используем |
|---|---|---|
| Microsoft Visio | эталон коннекторов и трафаретов, ShapeSheet, данные фигур, vsdx | только Windows, дорогой, отдельная покупка, тяжёлый формат |
| LibreOffice Draw | бесплатный, кроссплатформенный, ODF, многостраничный | примитивная маршрутизация, нет трафаретов с данными, слабый импорт vsdx |
| draw.io / diagrams.net | бесплатный, богатые библиотеки фигур, простота | веб/Electron, нет масштаба чертежа и размерных линий, нет данных фигур, слабая печать |
| Lucidchart / Miro | совместная работа, шаблоны | только облако, подписка, экспорт с потерями |
| OmniGraffle | качество, macOS-нативность | только Apple, дорогой |
| Inkscape | полноценная векторная графика, SVG | не инструмент для схем: нет коннекторов с маршрутизацией, трафаретов, данных |
1.2 Чем Draw будет лучше — конкретно
| Свойство | Как достигаем |
|---|---|
| Маршрутизация уровня Visio, но быстрее | ортогональный граф видимости + A* с штрафами за изломы/пересечения, инкрементальный пересчёт по R-дереву, фоновый поток |
| Трафареты — те же документы | трафарет = пакет .mvx с ролью stencil;
любую фигуру можно сохранить как мастер; мастера наследуются
экземплярами |
| Импорт vsdx с «живым» поведением | значения V для точного вида + интерпретатор
подмножества формул ShapeSheet для регуляторов и размеров |
| Данные в фигурах и связь с таблицей | типизированные поля, связывание строк Sheets/CSV/Base по ключу, графика данных, фигуры из строк |
| Автоматическая раскладка графов | Sugiyama (слоистая), Walker (деревья), круговая, радиальная, mind map, силовая |
| Один движок со Slides/Write | meridian-scene: 187 фигур DrawingML, те же стили, тот
же текстовый движок, тот же рендер Skia |
| Инженерные возможности | масштаб чертежа, единицы, размерные линии, слои с блокировкой и печатью, DXF |
| Локально, без подписки | Home включает Draw; никаких облачных ограничений |
1.3 Границы версии 1.0
В 1.0 — все P0. Бинарный .vsd, силовая раскладка,
проверка диаграмм (validation), совместная работа, AWS/Azure-наборы и
.cdr — P1/P2 по разделам ниже.
2. Функции
2.1 Документ и страницы
| Функция | P | Поведение |
|---|---|---|
| Многостраничный документ: добавить/дублировать/удалить/переименовать/переставить страницы, вкладки страниц внизу, обзор страниц (DR-04) | P0 | — |
| Размер страницы: пресеты (A0–A5, ANSI A–E, Letter/Legal/Tabloid, экранные 16:9/4:3, «произвольный»), ориентация, поля печати; автоувеличение страницы при выходе фигур за край (как Visio) | P0 | — |
| Масштаб чертежа (1:1, 1:2 … 1:1000, архитектурные 1/4″=1′, свой) и единицы (мм, см, м, дюйм, фут, пункт, px); линейки и координаты в единицах чертежа | P0 | Page.scale, Page.units |
| Фоновые страницы: страница может ссылаться на фоновую (логотипы, рамки, штампы); цепочка фонов | P0 | — |
| Штамп/рамка по ГОСТ 2.104 и ISO 5457 как фоновые шаблоны | P1 | шаблоны .mvt |
| Печать с разбиением на листы (tiling), перекрытие, метки реза; масштаб печати; предпросмотр разбиения (DR-09) | P0 | Meridian Print |
| Водяной знак, цвет фона страницы, прозрачный фон при экспорте | P0 | — |
| Защита: пароль на открытие, только чтение | P0 | как в Write |
2.2 Слои
| Функция | P | Поведение |
|---|---|---|
| Слои страницы: имя, цвет (подсветка), видимость, блокировка, печать, привязка (участие в snapping), прозрачность, порядок | P0 | фигура принадлежит одному или нескольким слоям (как в Visio) |
| Активный слой для новых фигур; перенос фигур между слоями; «показать только слой»; слои из мастера при вставке создаются автоматически | P0 | — |
Слои в экспорте: SVG (<g data-m-layer>), PDF (OCG
— необязательные группы содержимого) |
P0 / P1 | — |
2.3 Сетка, линейки, направляющие, привязки
| Функция | P | Поведение |
|---|---|---|
| Сетка: фиксированный шаг или динамическая (1/2/5·10ⁿ единиц по масштабу), мелкая/крупная, точки/линии, начало отсчёта | P0 | — |
| Линейки с единицами чертежа, вытягивание направляющих из линеек, направляющие под углом, точки-направляющие, блокировка | P0 | — |
| Привязка: к сетке, к направляющим, к геометрии фигур (вершины, середины, центры, пересечения), к точкам приклеивания, к расширениям линий (продолжения сторон), к равным интервалам/размерам; умные направляющие (§5.3) | P0 | диалог DR-26 |
| Угловая привязка при рисовании/повороте (15°, Shift — 45°) | P0 | — |
Временное отключение — Alt |
P0 | — |
2.4 Фигуры и кривые
| Функция | P | Поведение |
|---|---|---|
Примитивы: прямоугольник, эллипс, линия, дуга, многоугольник,
звезда, 187 фигур DrawingML (prstGeom, см.
docs/apps/slides.md §2.5) с регуляторами |
P0 | meridian-scene |
| Кривые Безье: инструмент «перо» (щелчок — угловой узел, протяжка — гладкий), карандаш (свободное рисование с упрощением §5.8), «кривая через точки» (Catmull-Rom → Безье) | P0 | — |
| Редактор узлов (DR-06): выбор/перемещение узлов и рукояток, типы узлов — угловой/гладкий/симметричный, добавить (двойной клик)/удалить, разорвать/соединить, замкнуть/разомкнуть, линия ↔︎ кривая для сегмента, выпрямить, обратить направление; общий редактор используется Slides/Write | P0 | custGeom |
| Трансформации: перемещение, масштаб (с Shift/Ctrl), поворот (маркер, центр вращения перемещаемый), отражение, наклон (skew), числовой ввод в DR-14 | P0 | Transform2D = аффинная матрица |
| Выравнивание/распределение/одинаковый размер/авторазмещение по сетке; порядок z; группировка (вложенная), «войти в группу» (редактирование детей на месте) | P0 | — |
| Дублирование со смещением, массив (сетка n×m, по кругу) | P0 / P1 | — |
| Поведение фигуры (из мастера): 1D (линия с началом/концом) или 2D; масштабирование: пропорционально / только ширина / без масштабирования частей (например, толщина стен) | P0 | ShapeBehaviour |
| Замена фигуры с сохранением текста, данных, коннекторов и размера | P0 | — |
| Защита фигуры: от перемещения, размера, поворота, удаления, выделения, текста, выхода из группы | P0 | Locks |
2.5 Булевы операции над контурами
| Операция | P | Результат |
|---|---|---|
| Объединить (union) | P0 | один контур, стиль верхней фигуры |
| Вычесть (difference, из нижней вычитаются верхние) | P0 | — |
| Пересечь (intersection) | P0 | — |
| Исключить (XOR) | P0 | — |
| Разделить (fragment — все части как отдельные фигуры) | P0 | — |
| Обрезать (trim — разрезать линии/контуры по точкам пересечения) | P1 | — |
| Соединить (join — конечные точки линий в один контур), сдвиг контура (offset/inset) | P1 | kurbo::offset |
| Преобразовать текст в контуры, обводку в контур | P1 | через глифы шрифта |
2.6 Текст
| Функция | P | Поведение |
|---|---|---|
| Текст в любой фигуре (движок Write: абзацы, списки, стили символов, RTL, вертикальный), блок текста с положением (центр/верх/низ/снаружи под фигурой/сбоку — «текстовый блок» перемещаемый отдельно, как в Visio) | P0 | — |
| Независимые надписи (text box) с автоподбором размера по тексту, фиксированной шириной с переносом | P0 | — |
| Текст по пути: вдоль открытой/замкнутой кривой, смещение по пути, сторона (внутри/снаружи), выравнивание начало/центр/конец, расстояние от линии (§5.9) | P0 | — |
Поля в тексте: данные фигуры {Prop.Стоимость},
геометрия {Width}, страница, дата, номер, пользовательские
формулы |
P0 | как Visio Field |
| Заливка текстового блока, поворот текста независимо от фигуры, поля блока | P0 | — |
| Орфография (Lingo), поиск и замена по тексту и данным | P0 | — |
2.7 Коннекторы
| Функция | P | Поведение |
|---|---|---|
| Типы: прямой, ломаный (ортогональный, по умолчанию), кривой (Безье); переключение для страницы и для коннектора | P0 | — |
| Точки приклеивания фигур: стандартные (центры сторон, центр), из мастера, пользовательские (редактор DR-31: тип «внутрь/наружу/обе», направление выхода); динамическое приклеивание к фигуре (конец выбирает ближайшую точку/сторону при перемещении) | P0 | GluePoint |
| Автомаршрутизация с обходом фигур, минимизацией изломов и пересечений, разведением параллельных линий (§5.1); перерасчёт при перемещении фигур в реальном времени | P0 | meridian-route |
| Ручная правка маршрута: перетаскивание сегментов (фиксация), добавление/удаление вершин, «сбросить маршрут» | P0 | — |
| Стрелки/маркеры (библиотека 30 + свои), толщина, штрих, скругление углов ломаной, перекрёстки (дуга/разрыв/нет) при пересечении | P0 | — |
| Метки на коннекторе (несколько, с позицией по длине, фоном, поворотом вдоль линии) | P0 | — |
| Быстрое соединение (AutoConnect): синие стрелки у выделенной фигуры → клонирование фигуры с соединением в направлении; соединение перетаскиванием на стрелку | P0 | DR-71 |
| Инструмент «Коннектор» и «Соединить фигуры» (цепочкой, в выбранном порядке, звезда) | P0 | — |
| Параметры маршрутизации страницы: стиль (ортогональный/прямой/центр-к-центру/блок-схема сверху вниз/слева направо/дерево/простой), интервалы от фигур, расстояние между линиями, перекрёстки, «избегать ли фигуры», «коннекторы под фигурами» | P0 | DR-25 |
| Направленность (стрелка на конце по умолчанию для направленных трафаретов), «перевернуть направление» | P0 | — |
2.8 Трафареты и библиотеки
Трафарет — документ Draw с ролью stencil: набор мастеров
(прототипов) с именем, описанием, значком, данными и поведением. Панель
«Фигуры» (DR-10) показывает открытые трафареты, поиск по всем
встроенным, «Избранное», «Недавние», «Мои фигуры» (личный трафарет, куда
можно перетаскивать фигуры). Встроенные библиотеки 1.0:
| Библиотека | Состав (мастера) | P |
|---|---|---|
| Базовые фигуры | 187 DrawingML + стрелки, звёзды, выноски, скобки (общий набор) | P0 |
| Блок-схема (базовая) | процесс, альтернативный процесс, решение, данные (ввод/вывод), предопределённый процесс, документ, несколько документов, терминатор, подготовка, ручной ввод, ручная операция, соединитель, межстраничный соединитель, карта, лента, суммирование, ИЛИ, сравнение, сортировка, извлечение, слияние, автономное/оперативное хранилище, магнитная лента/диск/барабан, дисплей, задержка, база данных, облако, примечание — 32 | P0 |
| Блок-схема ISO 5807 / ЕСПД ГОСТ 19.701-90 | полный набор символов стандарта с правильными пропорциями, функциональные дорожки | P0 |
| Межфункциональная блок-схема | пул, дорожки (вертикальные/горизонтальные), фазы, разделители | P0 |
| UML | класс (класс, интерфейс, перечисление, пакет, ассоциация/агрегация/композиция/наследование/реализация/зависимость с кратностями), последовательность (линия жизни, активация, сообщения синхр./асинхр./ответ/создание/уничтожение, фрагменты alt/loop/opt/par), активность (действие, решение/слияние, разделение/соединение, начало/конец, дорожки, объект), состояния (состояние, составное, начальное/конечное, история, переходы), варианты использования (актёр, вариант, система, include/extend), компоненты (компонент, порт, интерфейс, артефакт), развёртывание (узел, устройство, среда исполнения), объекты, пакеты — ≈ 120 | P0 |
| BPMN 2.0 | события (начальное/промежуточное/конечное × 13 типов, граничные прерывающие/непрерывающие), задачи (пользовательская, сервисная, скрипт, ручная, бизнес-правило, отправка/получение, подпроцесс, вызов, транзакция, ad-hoc, циклы/мульти-экземпляр), шлюзы (эксклюзивный, параллельный, включающий, событийный, комплексный), потоки (последовательности, сообщений, ассоциации, условный/по умолчанию), пулы и дорожки, артефакты (объект данных, хранилище, группа, аннотация), хореография — ≈ 90 | P0 |
| Сущность-связь (ER) | нотации Crow's Foot, Chen, IDEF1X, UML-данные; сущность с атрибутами (таблица), ключи, связи с кардинальностями | P0 |
| DFD (Йордон/Гейн-Сарсон) | процесс, внешняя сущность, хранилище, поток | P0 |
| Сетевые схемы | серверы (стойка, башня, виртуальный), маршрутизатор, коммутатор L2/L3, межсетевой экран, точка доступа, ПК/ноутбук/телефон/планшет/принтер, облако, интернет, VPN, балансировщик, NAS/SAN, стойка 42U с юнитами, кабели (Ethernet, оптика, последовательный) — ≈ 80, стиль «контурный MDS» и «цветной» | P0 |
| Электрические схемы (IEC 60617 + ANSI) | резистор (IEC/ANSI), конденсатор (пол./непол.), катушка, трансформатор, диод/стабилитрон/LED, транзисторы (BJT/MOSFET), источники (DC/AC/батарея), заземление, ключи/реле/кнопки, предохранитель, лампа, двигатель, измерители (A/V), разъёмы, логические элементы (AND/OR/NOT/NAND/NOR/XOR в IEC и ANSI), триггеры, ОУ — ≈ 110; обозначения позиций (R1, C2…) автонумерация | P0 |
| Планы помещений | стены (с толщиной, соединение углов), двери (распашная/раздвижная, с дугой открывания), окна, проёмы, лестницы, колонны; мебель (офис, дом, кухня, санузел), техника, озеленение, парковка; масштаб 1:50/1:100, размерные линии автоматически | P0 |
| Организационные диаграммы | должность, руководитель, помощник, вакансия, консультант, несколько стилей карточек (имя/должность/фото/отдел), мастер «из таблицы» (Sheets/CSV: имя, руководитель, должность) | P0 |
| Mind map | центральная тема, тема, подтема, плавающая тема, связи, выноски; авто-раскладка слева/справа, цвета ветвей | P0 |
| Диаграммы причин (Исикава), Венна, SWOT, матрицы, воронки, временные шкалы, пирамиды | набор маркетинговых/аналитических схем | P0 |
| C4 model | контекст/контейнер/компонент/код: person, software system, container, component, relationship | P1 |
| Веб-прототипы (wireframes) | окно браузера, мобильный экран, кнопки, поля, списки, таблицы, меню, диалоги, значки | P1 |
| Облачные архитектуры | AWS, Azure, GCP, Яндекс Облако, VK Cloud — наборы значков по лицензиям вендоров (загружаемые пакеты, не в дистрибутиве) | P1 [Pro: DrawStencilsPro] |
| ArchiMate 3, SysML (подмножество), IDEF0, Диаграммы Ганта (статичные), P&ID (технологические схемы), гидравлика/пневматика ISO 1219 | — | P2 |
| Карты (регионы РФ, страны мира, субъекты) как фигуры с данными | — | P2 |
| Функция | P | Поведение |
|---|---|---|
| Создание трафарета, сохранение фигуры как мастера (с данными, поведением, точками приклеивания, значком), редактирование мастера (DR-03) с обновлением экземпляров по подтверждению | P0 | — |
| Поиск фигур по имени/ключевым словам/библиотеке (русские и английские названия), фильтр | P0 | индекс в профиле |
Импорт трафаретов .vssx/.vssm/.vsx (Visio) и библиотек
draw.io (.xml библиотеки) |
P0 / P1 | — |
| Магазин трафаретов (фаза 7) | P2 | — |
2.9 Размерные линии
| Функция | P | Поведение |
|---|---|---|
| Линейный (гор./верт.), выровненный (под углом), угловой, радиус, диаметр, ординатный, цепочка, базовый | P0 (линейный, выровненный, угловой, радиус/диаметр) / P1 (остальные) | §5.12 |
| Привязка концов к точкам геометрии фигур с пересчётом при изменении; значение × масштаб чертежа; формат числа, единицы, точность, допуски (P1), префикс/суффикс, переопределение текста | P0 | — |
| Стиль размеров (стрелки, выносные линии, отступы, шрифт) на документ/слой; ГОСТ 2.307 и ISO 129 пресеты | P0 | DR-34 |
| Авторазмеры для стен/планов | P1 | — |
2.10 Контейнеры, списки, дорожки
| Функция | P | Поведение |
|---|---|---|
| Контейнер: заголовок, стиль, авторазмер (всегда вмещать / при добавлении / нет), поля; членство при перетаскивании внутрь; перемещение/копирование/удаление с членами; «отключить от контейнера» | P0 | §5.10 |
| Список: упорядоченные члены (вертикально/горизонтально), автопозиционирование, вставка между элементами, «место вставки» при перетаскивании | P0 | — |
| Дорожки (swimlanes) и пулы: ориентация, добавление дорожек, изменение ширины с перераспределением, фазы (столбцы) | P0 | контейнер-список контейнеров |
| Выноски, привязанные к фигурам (перемещаются вместе) | P0 | — |
2.11 Данные фигур и связывание
| Функция | P | Поведение |
|---|---|---|
| Данные фигуры (Shape Data): типизированные поля — строка, число, денежный, дата, длительность, логический, фиксированный список, список с вводом; метка, подсказка, формат, скрытое, порядок; определения из мастера; панель DR-12 для правки | P0 | DataField |
Отображение данных в тексте фигуры (поля {Prop.X}) и
графикой данных: текстовые выноски, наборы значков (по порогам), заливка
по значению (шкалы), гистограмма-полоска; положение относительно фигуры;
легенда |
P0 (текст, значки, заливка) / P1 (полоски, легенда) | DR-38 |
Связь с внешними данными: Sheets (.msx,
лист/диапазон/таблица), .xlsx, CSV, Meridian Base/SQLite,
запрос SQL (коннекторы Base [Pro]); мастер DR-23; окно
«Внешние данные» (DR-16) со строками; связывание строки с фигурой
(перетаскивание строки на фигуру / автоматически по ключу), создание
фигур из строк (мастер по умолчанию, авто-раскладка), обновление
(ручное/при открытии/по расписанию скриптом), обнаружение
новых/удалённых/изменённых строк |
P0 (Sheets, CSV, xlsx) / P1 (Base, SQL) | §5.11 |
| Отчёты по данным: таблица из полей выбранных фигур → Sheets/Write | P1 | — |
| Проверка диаграмм (validation): правила для блок-схем/BPMN (висячие коннекторы, нет начала/конца, несоединённые фигуры), панель проблем | P2 | — |
2.12 Автоматическая раскладка
| Функция | P | Алгоритм |
|---|---|---|
| Иерархическая слоистая (сверху вниз / слева направо / снизу / справа) для направленных графов — блок-схемы, процессы, зависимости | P0 | Sugiyama (§5.6) |
| Дерево / организационная (вертикальная, горизонтальная, «боком», «висячие» ветви, помощники) | P0 | Walker/Buchheim (§5.7) |
| Круговая, радиальная (концентрические уровни) | P0 | §5.7 |
| Mind map (сбалансированное дерево слева/справа) | P0 | §5.7 |
| Силовая (органичная) для неориентированных графов | P1 | Fruchterman–Reingold + Barnes–Hut |
| Параметры: интервалы, выравнивание, учёт размеров фигур, сохранение порядка, применить к выделению/странице, авторазмер страницы после раскладки, отмена одним шагом | P0 | диалог DR-24 |
| Раскладка «на лету» при добавлении через AutoConnect (локальная) | P1 | — |
2.13 Стили и темы
| Функция | P | Поведение |
|---|---|---|
Тема документа (цвета 12, шрифты, эффекты — общая Theme
ядра) + «варианты» и «цвета коннекторов»; быстрые стили фигур (матрица
темы, как в Slides) |
P0 | — |
| Именованные стили фигур (заливка, линия, текст, тень — с наследованием «на основе»), применение/обновление по образцу, стили линий/коннекторов, стили текста | P0 | styles.xml |
| Заливки, линии, эффекты — как в Slides §2.5 (включая градиенты, узоры, изображения, тени, свечение); дополнительно: штриховки (hatch) инженерные ANSI 31/ISO | P0 | — |
| Копировать формат, «применить стиль ко всем фигурам этого мастера» | P0 | — |
2.14 Изображения
Вставка растров и SVG (как в Slides §2.6–2.7), обрезка, коррекция, прозрачный цвет; «трассировка» растра в контуры (потенциальная функция Paint — P2); EMF/WMF импортируются как векторные группы.
2.15 Экспорт и импорт
| Формат | Чтение | Запись | P |
|---|---|---|---|
.mvx/.mvt/.mvxf |
полное | полное | P0 |
.svg (1.1, подмножество 2.0) |
полное для статики (path, формы, текст, градиенты, clipPath, маски,
use, символы), фильтры частично |
полное: слои, id, классы, метаданные Meridian, встроенные шрифты как
контуры (опц.), текст как <text> |
P0 |
.odg (ODF Drawing) |
полное | полное | P0 |
.vsdx/.vsdm/.vstx (Visio 2013+) |
полное (§7.3) | подмножество [Pro: DrawVsdxExport] |
P0 чтение / P1 запись |
.vssx/.vssm трафареты Visio |
полное | — | P0 |
.vsd/.vss/.vst (Visio 2003–2010, бинарный) |
фигуры, текст, страницы, слои, коннекторы, мастера | — | P1 |
.drawio / .xml diagrams.net |
полное для стандартных библиотек, сжатые и несжатые, многостраничные | экспорт | P0 чтение / P1 запись |
.dxf (R12–2018) |
LINE, LWPOLYLINE, POLYLINE, CIRCLE, ARC, ELLIPSE, SPLINE, TEXT, MTEXT, INSERT/BLOCK, LAYER, DIMENSION, HATCH (сплошная/простые) | экспорт | P0 чтение / P1 запись |
.emf/.wmf |
GDI-записи → фигуры; EMF+ базово | EMF (Windows и собственный писатель) | P0 |
.cdr (CorelDRAW X4+, подмножество) |
фигуры, кривые, текст, заливки | — | P2 |
.pdf |
импорт страницы как векторной группы (через Meridian PDF, фаза 4) | экспорт (вектор, многостраничный, слои как OCG P1, PDF/A) | P2 / P0 |
.png/.jpg/.webp/.tiff |
как изображение | экспорт страницы/выделения/всего, dpi, прозрачность, обрезка по содержимому | P0 |
.pptx/.docx |
— | копирование фигур в Slides/Write через общий буфер сцены (не экспорт файла) | P0 |
2.16 Навигация и представление
| Функция | P | Поведение |
|---|---|---|
| Масштаб 1 %–10 000 %, панорамирование (пробел+перетаскивание, колесо, жесты), навигатор-миниатюра (панорама), «вписать страницу/выделение/всё» | P0 | — |
| Полноэкранный просмотр и показ страниц (как слайды, со стрелками) | P0 | DR-05 |
| Гиперссылки у фигур: страница, фигура, внешний файл, URL, несколько ссылок на фигуру | P0 | — |
| Поиск по тексту, именам, данным фигур; «выделить по типу/мастеру/слою/стилю» | P0 | DR-39 |
| Навигатор: дерево страниц → слои → фигуры (имена), выбор, переименование | P0 | DR-15 |
2.17 Рецензирование и совместная работа
Комментарии к фигурам/страницам с ответами и статусом (P0),
рукописные пометки (P1), сравнение страниц (P2); совместная работа CRDT
(фаза 6, [Pro: CloudCollab]): сцена страницы — CRDT-карта
узлов, присутствие, история версий.
2.18 Доступность
Дерево доступности: фигуры в порядке чтения (настраиваемом), текст, данные; alt-текст у фигур и страниц; полная клавиатурная навигация (переход между фигурами, по коннекторам «к следующей соединённой фигуре»); высокая контрастность; экспорт PDF/UA с тегами и описанием схемы; проверка доступности (P1).
2.19 Скрипты и Assist
Вкладка «Скрипты» ([Home+]), API §6, события (открытие,
изменение данных, добавление фигуры, соединение); Assist
([Pro], фаза 7): «схема из текста» (описание процесса →
блок-схема), автоподписи, перевод текста фигур.
3. Экраны
Идентификаторы: DR-01…DR-09 — главное окно, виды и
режимы; DR-10…DR-19 — панели; DR-20…DR-59 —
диалоги; DR-60…DR-69 — контекстные меню;
DR-70+ — всплывающие элементы. Макет —
mockups/draw.html.
3.1 DR-01 Главное окно
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ [⌁] Сеть офиса.mvx — Meridian Draw [⌘K Поиск команд] [☁ Сохранено] [👤] │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ Файл Главная Вставка Дизайн Данные Рецензирование Вид Скрипты │ Коннектор │
│ [Буфер][Шрифт][Абзац][Сервис][Стили фигур][Упорядочение][Редактирование] [⌄] │
├──────────────┬─────────────────────────────────────────────────────────┬───────────────┤
│ ФИГУРЫ │ ╷0 ╷50 ╷100 ╷150 мм │ Данные фигуры │
│ 🔍 поиск │ ─ ┌───────────────────────────────────────────────────┐ │ Имя: SW-01 │
│ ▸ Избранное │ 0 │ ┌──────┐ ┌──────┐ │ │ IP: 10.0.0.2 │
│ ▾ Сетевые │ │ │Роутер│──────────│Коммут│──┐ │ │ Стойка: A3 │
│ [▭][▭][▭] │ 50│ └──────┘ └──┬───┘ │ │ │ Порты: 48 │
│ [▭][▭][▭] │ │ │ └──▶┌──────┐ │ ├───────────────┤
│ ▸ Блок-схема │100│ ┌─────┴────┐ │Сервер│ │ │ Слои │
│ ▸ UML │ │ │ ПК ×12 │ └──────┘ │ │ ☑ 🔓 Сеть │
│ ▸ Мои фигуры │ └───────────────────────────────────────────────────┘ │ ☑ 🔒 Фон │
├──────────────┴──┬───────────┬───────────┬──────────────────────────────┴───────────────┤
│ ◂ ▸ │ Этаж 1 │ Этаж 2 │ Фон-рамка ▪ │ ⊕ │ [Внешние данные ▲] │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ Стр. 1 из 3 · Слой: Сеть · Выделено 2 · 120,0 × 45,0 мм · ∠0° · Масштаб 1:50 │ ─●─ 75 % ⤢ │
└────────────────────────────────────────────────────────────────────────────────────────┘
Холст: линейки сверху/слева (единицы чертежа, маркеры курсора),
сетка, направляющие, страница с тенью; маркеры выделения (8 размерных,
поворот, центр вращения, регуляторы, точки приклеивания при наведении с
коннектором), синие стрелки AutoConnect (DR-71), подсветка фигуры-цели
при приклеивании (рамка --app-draw), синяя пунктирная рамка
контейнера при перетаскивании внутрь, подсказки координат/размеров/угла
у курсора (--m-sun).
3.2 Остальные виды и режимы
| ID | Экран | Описание |
|---|---|---|
| DR-02 | Панель «Фигуры» (развёрнутая) | левая панель 220–360 px: поиск (мгновенный, по всем библиотекам), вкладки «Избранное / Открытые трафареты / Все библиотеки / Мои фигуры»; трафарет — заголовок (сворачиваемый, значок, ⋯ меню: закрыть, редактировать, сохранить как, свойства), сетка значков 48/32 px или список с именами; перетаскивание на холст, двойной клик — в центр; «Быстрые фигуры» — первые 4 мастера трафарета для AutoConnect |
| DR-03 | Редактор трафарета / мастера | вкладка-документ с ролью stencil: список мастеров слева, холст мастера (локальные координаты, точки приклеивания, регуляторы, текстовый блок), панель свойств мастера (имя, подсказка, ключевые слова, значок: авто/из файла, поведение 1D/2D, масштабирование, данные по умолчанию, авто-слои); «Применить к экземплярам» |
| DR-04 | Обзор страниц | сетка миниатюр страниц с именами, фоновые страницы с меткой, перетаскивание порядка, мультивыбор, свойства по двойному клику |
| DR-05 | Полноэкранный просмотр | страница на весь экран, навигация стрелками/колесом, гиперссылки активны, масштабирование, выход Esc |
| DR-06 | Режим редактирования узлов | ручки узлов (квадрат — угловой, круг — гладкий, ромб — симметричный), рукоятки, подсветка сегмента под курсором, мини-панель DR-72 |
| DR-07 | Режим точек приклеивания | точки (×) на фигуре, добавление Ctrl+клик, перетаскивание, тип/направление в мини-панели, удаление Delete |
| DR-08 | Режим «Данные» | внизу окно внешних данных DR-16 (развёрнуто), на фигурах — значки связи, графика данных |
| DR-09 | Предпросмотр печати и разбиения | страница с сеткой листов, перекрытие, масштаб, «уместить на 1×1», порядок листов |
3.3 Ribbon — вкладки и группы
| Вкладка | Группы (команды) |
|---|---|
| Файл (backstage) | Создать (шаблоны по категориям: блок-схемы, UML, BPMN, сеть, планы,
орг., mind map, пустой), Открыть, Сведения (защита, свойства, трафареты
документа, внешние связи), Сохранить, Сохранить как, Экспорт (SVG, PDF,
PNG/JPG, EMF, vsdx [Pro], drawio, dxf), Печать (DR-33),
Поделиться (фаза 6), Параметры (DR-40) |
| Главная | Буфер обмена · Шрифт · Абзац · Сервис (указатель▾: указатель/область/лассо; коннектор; текст; точка приклеивания; перо▾: перо/карандаш/линия/дуга/прямоугольник/эллипс) · Стили фигур (галерея, заливка▾, линия▾, эффекты▾) · Упорядочение (выровнять▾, положение▾: распределить/повернуть/отразить/группа; вперёд/назад▾; авторазмещение) · Редактирование (найти, выделить▾: по типу/мастеру/слою/все, слои▾: назначить/свойства, заменить фигуру▾) |
| Вставка | Страницы (новая страница▾, фоновая) · Иллюстрации (рисунки, SVG, диаграмма Chart, фигуры▾ 187, контейнер▾, выноска▾, список) · Текст (надпись, текст по пути, поле▾, дата/номер) · Трафареты (открыть▾, новый, «Мои фигуры») · Размеры (линейный, выровненный, угловой, радиус/диаметр, стиль) · Ссылки (гиперссылка) · Комментарии · Объект Math |
| Дизайн | Параметры страницы (ориентация, размер▾, автоувеличение, масштаб чертежа → DR-42, фоновые▾, рамки и заголовки▾) · Темы (галерея, варианты, цвета коннекторов▾) · Макет (автораскладка▾ → DR-24, коннекторы▾: стиль/перекрёстки/параметры DR-25) · Фон (цвет, водяной знак) |
| Данные | Внешние данные (связать с данными → DR-23, обновить все▾, окно «Внешние данные» ☑) · Данные фигуры (окно ☑, определить поля → DR-22, из выделения) · Графика данных (применить▾, создать → DR-38, легенда) · Отчёты (создать отчёт P1) · Автосвязь (по ключу) |
| Рецензирование | Правописание · Доступность · Комментарии (создать, показать, следующий/предыдущий) · Рукописный ввод (P1) · Проверка диаграммы (P2: проверить, правила▾, окно проблем) · Защита (пароль, только чтение, защита фигур) · Сравнить (P2) |
| Вид | Представления (обычный, полноэкранный, обзор страниц, презентация) · Показать (линейки, сетка, направляющие, точки приклеивания, разрывы страниц, панель фигур, навигатор, слои, размер и положение) · Визуальные подсказки (AutoConnect, динамическая сетка, умные направляющие) · Масштаб (масштаб, вписать страницу, вписать всё, 100 %, окно панорамы) · Окно · Фокус |
Скрипты [Home+] |
Код (редактор, записать, выполнить▾, отладчик) · Документ (скрипты документа, события, расписания) · Кнопки (на странице, в ленте) · Безопасность |
| Формат фигуры (контекст) | Вставка фигур (галерея, изменить фигуру▾, объединить▾: объединить/вычесть/пересечь/исключить/разделить/обрезать) · Стили фигур · Стили WordArt · Текстовый блок (положение▾, поворот) · Упорядочение · Размер (ширина, высота, угол, блокировка пропорций) · Защита▾ · Поведение (1D/2D, масштабирование▾) |
| Коннектор (контекст) | Тип (прямой/ломаный/кривой) · Маршрут (перенаправить, сбросить, ручной сегмент) · Концы (начало▾, конец▾, перевернуть) · Метки (добавить, положение) · Перекрёстки▾ · Стили линий |
| Контейнер / Список / Дорожки (контекст) | Размер (вписать содержимое, авторазмер▾, поля) · Стиль заголовка▾ · Членство (выделить содержимое, отключить, заблокировать) · Дорожки (добавить до/после, ориентация, фазы) |
| Текст по пути (контекст) | Путь (сторона, смещение, выравнивание, отступ от линии, показать путь) |
| Размерная линия (контекст) | Тип, стиль▾, точность, единицы, переопределить текст, перепривязать |
| Формат рисунка (контекст) | как в Slides |
| Трафарет (контекст, в DR-03) | Мастера (новый, дубликат, удалить, из выделения) · Свойства · Значок (обновить, из файла) · Применить к экземплярам · Сохранить трафарет |
3.4 Панели
| ID | Панель | Описание |
|---|---|---|
| DR-10 | Фигуры (слева) | см. DR-02; сворачивается в узкую полосу значков трафаретов |
| DR-11 | Слои (справа) | таблица: цвет, имя, видимость (глаз), блокировка (замок), печать (принтер), привязка (магнит), прозрачность; активный слой (жирный); кнопки добавить/удалить/объединить; перетаскивание порядка; контекст: выделить фигуры слоя, свойства DR-21 |
| DR-12 | Данные фигуры (справа) | список полей выделенной фигуры: метка, значение (редактор по типу: текст, число с форматом, календарь, список, флажок); для нескольких фигур — общие поля; кнопки «Определить поля» (DR-22), «Применить графику» |
| DR-13 | Формат фигуры (справа) | аккордеон: Заливка, Линия (включая маркеры/штрих/скругление), Эффекты, Текст (положение блока, поля, автоподбор), Размер и положение (дублирует DR-14), Поведение, Защита, Alt-текст |
| DR-14 | Размер и положение (плавающая/док) | X, Y (центра/угла — переключатель), ширина, высота, угол, центр
вращения, начало/конец (для 1D), единицы; ввод выражений
(=10mm*2) |
| DR-15 | Навигатор (слева, вкладка над «Фигурами») | дерево: страницы → слои → фигуры (имя, тип, значок); поиск; клик — выделить и показать; переименование F2; перетаскивание между слоями |
| DR-16 | Внешние данные (внизу) | вкладки по источникам; таблица строк (сортировка, фильтр, поиск), статус связи (значок у строки: связана/новая/изменена/удалена), перетаскивание строки на холст/фигуру, «Связать по ключу», «Обновить», «Настроить столбцы» |
| DR-17 | Комментарии (справа) | как в Slides SL-14 с якорями к фигурам/страницам |
| DR-18 | Стили (справа) | именованные стили фигур/линий/текста, предпросмотр, создать из выделения, изменить, применить; «показать использование» |
| DR-19 | Раскладка (справа) | тип раскладки, направление, интервалы, предпросмотр «живьём» на выделении, применить/отмена (дублирует DR-24 в виде панели) |
| DR-70 | Мини-панель форматирования | шрифт, размер, Ж/К/Ч, цвет, заливка/линия, выравнивание, стиль фигуры |
| DR-71 | Стрелки AutoConnect | 4 синих треугольника у выделенной фигуры; наведение показывает «быстрые фигуры» трафарета; клик — вставка и соединение; перетаскивание на другую фигуру — соединение |
| DR-72 | Мини-панель узлов | тип узла (угловой/гладкий/симметричный), добавить/удалить, разорвать/соединить, замкнуть, линия/кривая |
| DR-73 | Подсказка измерений | у курсора при рисовании/перемещении: Δx/Δy, размер, угол, расстояние до соседа |
| DR-74 | Окно панорамы (навигатор-миниатюра) | уменьшенная страница с рамкой видимой области, перетаскивание |
3.5 Диалоги
| ID | Диалог | Содержимое |
|---|---|---|
| DR-20 | Параметры страницы | вкладки: Размер (пресеты, ширина/высота, ориентация, автоувеличение), Масштаб чертежа (пресеты, свой, единицы, «размер страницы в единицах чертежа»), Свойства (имя, тип: передняя/фоновая, фоновая страница▾, единицы измерения), Макет и маршрутизация (= DR-25), Тени (стиль/смещение), Печать (поля, масштаб, разбиение) |
| DR-21 | Свойства слоя / Слои | таблица слоёв (см. DR-11) + «новый», «удалить», «переименовать», «удалить неиспользуемые», для выделения — назначить слои (мультивыбор) |
| DR-22 | Определение данных фигуры | список полей; поле: метка, имя (идентификатор), тип, формат (шаблон числа/даты, список значений), значение по умолчанию, подсказка, порядок, скрыто; «применить к мастеру» |
| DR-23 | Связь с внешними данными (мастер) | шаг 1: источник (Sheets-файл, xlsx, CSV, Base/SQLite, SQL
[Pro]); шаг 2: лист/диапазон/таблица/запрос, первая строка
— заголовки; шаг 3: столбцы (включить, тип, ключ — уникальный
идентификатор строк); шаг 4: обновление (вручную / при открытии / каждые
N мин — скриптом); готово → DR-16 |
| DR-24 | Автоматическая раскладка | тип (слоистая, дерево, круговая, радиальная, mind map, силовая P1), направление, интервал между уровнями/узлами, выравнивание узлов, стиль коннекторов после раскладки, «применить к: выделению/странице», «изменить размер страницы», предпросмотр |
| DR-25 | Параметры маршрутизации страницы | стиль маршрута▾, направление, интервал от фигур (гор./верт.), расстояние между коннекторами, перекрёстки (стиль: дуга/разрыв/нет; размер), «обходить фигуры», «коннекторы под фигурами», скругление углов, «перемаршрутизировать всё сейчас» |
| DR-26 | Сетка и направляющие | привязка к: сетка, направляющие, геометрия, точки приклеивания, расширения, равные интервалы; сила привязки (px); сетка: тип (динамическая/фиксированная), шаг, мелкая/крупная, начало; показать/скрыть; направляющие: список с координатами/углом, блокировка, цвет |
| DR-27 | Экспорт SVG | область (страница/выделение/все страницы — по файлу на страницу), размер и единицы, текст: как текст/как контуры, слои как группы, встроить изображения/ссылки, метаданные Meridian (для обратного импорта без потерь), минимизировать, точность координат |
| DR-28 | Экспорт растра | формат, область, dpi или размер px, фон (прозрачный/цвет), поля, обрезка по содержимому, сглаживание |
| DR-29 | Экспорт PDF | страницы, вектор/растр, слои как OCG (P1), PDF/A, закладки по страницам, гиперссылки, встраивание шрифтов |
| DR-30 | Новый трафарет / Сохранить как мастер | имя трафарета (новый/существующий), имя мастера, подсказка, ключевые слова, значок, поведение, «включить данные», «заменить существующий» |
| DR-31 | Точки приклеивания | таблица точек: X, Y (абс./относительно размера %), тип (внутрь/наружу/обе), направление выхода (авто/угол), имя; добавить/удалить; предпросмотр |
| DR-32 | Гиперссылка | адрес/файл/страница (список) + фигура (список по именам), описание, «новое окно», несколько ссылок на фигуру |
| DR-33 | Печать и разбиение | принтер, страницы, копии, «текущий вид/страницы/все», масштаб (как есть/вписать на N×M листов/%), разбиение с перекрытием, метки, сетка/направляющие (печатать?), фон, цвет/серый, предпросмотр DR-09 |
| DR-34 | Стиль размерных линий | стрелки (тип/размер), выносные линии (отступ/выступ), положение текста, шрифт, формат числа (точность, разделители, единицы, суффикс), масштаб, пресеты ГОСТ/ISO/ANSI |
| DR-35 | Импорт DXF | единицы файла, масштаб, слои → слои Draw (все/выбор), блоки → группы/мастера, шрифты SHX → замена, цвета ACI → RGB/по слою, толщины, размер страницы по экстенту |
| DR-36 | Импорт drawio | страницы (все/выбор), сопоставление библиотек (стандартные → наши мастера, неизвестные → фигуры/изображения), шрифт по умолчанию |
| DR-37 | Параметры контейнера / списка | авторазмер, поля, заголовок (положение/стиль), список: направление, интервал, выравнивание, «разрешить перетаскивание из/в» |
| DR-38 | Графика данных | набор правил: поле → тип (текст/значок/заливка/полоска), положение, порог/шкала/набор значков, формат; применить к выделению/мастеру; легенда |
| DR-39 | Поиск и выделение | искать в: текст/имена/данные/все страницы; условия по данным
(поле = значение, >, содержит); результат —
список с переходом; «выделить все найденные» |
| DR-40 | Параметры Draw | общие (единицы, язык), правка (привязка, AutoConnect, дублирование со смещением), сохранение, трафареты (пути), производительность (кэш, GPU, упрощение при масштабе), скрипты |
| DR-41 | Защита фигуры / документа | флажки блокировок; пароль документа |
| DR-42 | Масштаб чертежа | список стандартных, «по размеру объекта» (ввод реальной длины выбранного отрезка → масштаб) |
| DR-43 | Текст по пути | выбор пути (текущая кривая/новая), параметры (см. контекстная вкладка), предпросмотр |
| DR-44 | Замена фигуры | галерея мастеров/фигур, параметры сохранения (текст, данные, размер, коннекторы, стиль) |
| DR-45 | Массив | n×m, шаги, по кругу (центр, число, угол), «как копии/как экземпляры» |
| DR-60 | Контекстное меню фигуры | вырезать/копировать/вставить, дублировать, группировать▾, порядок▾, слои▾, данные▾ (изменить, определить), гиперссылка, формат, заменить фигуру, сохранить как мастер, контейнер▾ (добавить в/отключить), заблокировать, выравнивание▾ |
| DR-61 | Контекстное меню коннектора | тип▾, перенаправить, сбросить, перевернуть, концы▾, метка, перекрёстки, отклеить концы |
| DR-62 | Контекстное меню страницы (вкладка) | новая, дублировать, удалить, переименовать, параметры, фоновая▾, цвет вкладки, обзор страниц |
| DR-63 | Контекстное меню холста | вставить, выделить всё, сетка/направляющие, масштаб▾, параметры страницы, автораскладка, свойства |
| DR-64 | Контекстное меню трафарета | закрыть, редактировать, сохранить/сохранить как, свойства, значки/список, добавить в избранное |
4. Модель данных
4.1 Пакет .mvx
mimetype application/vnd.meridian.draw
manifest.xml части, версия, role = document | stencil | template
meta.xml Dublin Core + статистика (страницы, фигуры)
document.xml настройки документа: единицы, тема, порядок страниц, фоновые ссылки, стили маршрутизации по умолчанию
pages/page-<ulid>.xml страница: размер, масштаб, слои, узлы (фигуры/группы/коннекторы/текст/изображения), направляющие
masters/master-<ulid>.xml встроенные мастера (копии использованных мастеров трафаретов + свои)
stencil.xml только для role=stencil: список мастеров, порядок, значки, ключевые слова
styles.xml именованные стили фигур/линий/текста, стили размеров, стили данных
data/sources.xml источники внешних данных и кэш строк (data/cache-<ulid>.msx)
media/<sha256>.<ext> изображения, значки мастеров (thumbnails/master-<ulid>.png)
objects/chart-<ulid>.msx данные диаграмм, objects/*.meq — формулы
thumbnail.png первая страница 256 px
history/, scripts/, signatures/, settings.xml
4.2 Структуры ядра (Rust,
meridian-draw)
// kernel/crates/meridian-draw/src/model.rs
use meridian_scene::{Geometry, Fill, Line, Effects, TextBody, Theme, Transform2D};
use kurbo::{Affine, Point, Rect, Vec2};
pub struct Document {
pub id: Ulid,
pub role: DocRole, // Document | Stencil | Template
pub pages: IndexMap<Ulid, Page>, // порядок = порядок вкладок / tab order
pub masters: IndexMap<Ulid, Master>, // встроенные мастера / embedded masters
pub styles: StyleSheet, // именованные стили / named styles
pub theme: Theme,
pub units: Units, // Mm | Cm | M | In | Ft | Pt | Px
pub data_sources: Vec<DataSource>,
pub routing_defaults: RoutingOptions,
pub dim_styles: Vec<DimStyle>,
pub meta: DocMeta,
}
pub struct Page {
pub id: Ulid,
pub name: String,
pub kind: PageKind, // Foreground | Background
pub background: Option<Ulid>, // фоновая страница / background page
pub size: Size, // в единицах страницы (мм) / page units
pub scale: DrawingScale, // 1:50 → page_mm / drawing_unit
pub auto_size: bool,
pub layers: Vec<Layer>,
pub nodes: SlotMap<NodeId, Node>,
pub roots: Vec<NodeId>, // z-порядок корневых узлов / root z-order
pub guides: Vec<Guide>,
pub routing: RoutingOptions,
pub index: RTree<NodeId>, // пространственный индекс (не сериализуется) / spatial index
pub revision: u64,
}
pub struct Layer { pub id: LayerId, pub name: String, pub color: Option<Color>, pub visible: bool, pub locked: bool, pub printable: bool, pub snappable: bool, pub opacity: f32 }
pub struct Node { pub base: NodeBase, pub kind: NodeKind }
pub struct NodeBase {
pub id: NodeId,
pub name: String,
pub layers: SmallVec<[LayerId; 2]>,
pub transform: Affine, // локальные → родительские координаты / local → parent
pub size: Size, // локальный bbox 0..w, 0..h / local box
pub style: StyleRef, // именованный стиль + переопределения / named + overrides
pub fill: Option<Fill>, pub line: Option<Line>, pub effects: Option<Effects>,
pub text: Option<TextBlock>, // текст + положение блока / text + block placement
pub data: ShapeData, // §4.4
pub master: Option<MasterRef>, // экземпляр мастера / master instance
pub glue_points: Vec<GluePoint>,
pub hyperlinks: Vec<Hyperlink>,
pub locks: Locks,
pub alt_text: AltText,
pub parent: Option<NodeId>,
pub container: Option<NodeId>, // членство в контейнере (не родитель!) / container membership
pub ext: Vec<ExtensionBlob>,
}
pub enum NodeKind {
Shape { geometry: Geometry, behaviour: ShapeBehaviour }, // 2D-фигура / 2D shape
Line1D { geometry: Geometry, begin: Point, end: Point }, // 1D-фигура (стена, труба) / 1D shape
Group { children: Vec<NodeId>, child_space: Rect }, // группа / group
Connector(Connector),
Text { body: TextBody, auto_size: AutoSize }, // независимая надпись / standalone text
TextOnPath { body: TextBody, path: Geometry, params: PathTextParams },
Image { media: MediaRef, crop: Rect, effects: PicEffects },
Container(Container), // контейнер / список / дорожки
Dimension(Dimension),
Chart(ChartRef), Math(MathRef),
}
pub struct GluePoint { pub id: u16, pub pos: GluePos /* Abs(Point) | Rel(f64,f64) | Formula(GuideRef) */, pub dir: GlueDir /* Auto | Angle(f64) */, pub kind: GlueKind /* In | Out | InOut */, pub name: Option<String> }
pub struct Connector {
pub routing: RoutingKind, // Straight | Orthogonal | Curved
pub ends: [ConnectorEnd; 2],
pub waypoints: Vec<Waypoint>, // ручные ограничения: Fixed{axis, value} | Point
pub path: BezPath, // вычисленный маршрут (кэш, в мировых коорд.) / computed route
pub path_rev: u64, // ревизия, на которой посчитан / revision of computation
pub markers: (Marker, Marker),
pub labels: Vec<ConnectorLabel>, // { text, t: 0..1, offset, rotate_along }
pub jumps: JumpStyle,
pub corner_radius: f64,
}
pub enum ConnectorEnd { Free(Point), Glued { node: NodeId, point: GlueRef /* Fixed(u16) | Dynamic */ } }
pub struct Master {
pub id: Ulid, pub name: String, pub prompt: String, pub keywords: Vec<String>,
pub icon: MediaRef,
pub prototype: Page, // поддерево узлов в локальной системе / prototype subtree
pub behaviour: ShapeBehaviour, // OneD/TwoD, scaling, text position, glue defaults
pub data_defaults: Vec<DataField>,
pub layers: Vec<String>, // слои, создаваемые при вставке / auto-created layers
pub origin: MasterOrigin, // Builtin(stencil, ver) | User | Imported(vsdx, …)
pub formulas: Option<FormulaSet>, // параметрическое поведение (из vsdx или свои) / parametric rules
}
pub struct MasterRef { pub master: Ulid, pub overrides: Overrides } // что изменено в экземпляре / instance overridesИнварианты: roots и Group.children не
пересекаются; container ссылается только на узел
Container той же страницы; коннектор с Glued
концами хранит NodeId, при удалении фигуры концы становятся
Free с последней точкой; index перестраивается
инкрементально (вставка/удаление/изменение bbox).
4.3 Страница в XML
<page xmlns="urn:meridian:office:draw:1" id="01J9R0…" name="Этаж 1" width="420mm" height="297mm" scale="1:50" units="m">
<layers><layer id="1" name="Сеть" color="#0E8A8A"/><layer id="2" name="Фон" locked="true"/></layers>
<nodes>
<shape id="12" name="Роутер" layers="1" master="01J9R0M…" transform="1 0 0 1 40 60" w="30" h="18">
<geom preset="roundRect"><adj name="adj" val="16667"/></geom>
<text pos="below"><p><r>RT-01</r></p></text>
<data><field name="IP" type="string">10.0.0.1</field><field name="Rack" type="string">A3</field></data>
<glue><pt id="1" rel="0.5 0" dir="auto" kind="inout"/><pt id="2" rel="1 0.5"/><pt id="3" rel="0.5 1"/><pt id="4" rel="0 0.5"/></glue>
</shape>
<connector id="13" name="Линк 1" routing="orthogonal" layers="1">
<end glued="12" point="2"/><end glued="15" point="dynamic"/>
<waypoint axis="y" value="69"/>
<marker end="arrow" size="m"/>
<label t="0.5">1 Гбит/с</label>
<path cache="M 70 69 L 110 69 L 110 95 L 140 95"/>
</connector>
</nodes>
<guides><guide axis="x" value="40"/></guides>
</page>Элемент <path cache> хранит последний вычисленный
маршрут — документ открывается без немедленного пересчёта; пересчёт
выполняется лениво при изменениях.
4.4 Данные фигур и связи
pub struct ShapeData { pub fields: IndexMap<SmolStr, DataField>, pub link: Option<DataLink> }
pub struct DataField { pub name: SmolStr, pub label: String, pub kind: DataKind, pub value: DataValue, pub format: Option<String>, pub prompt: String, pub hidden: bool, pub sort_key: u16, pub inherited: bool /* из мастера / from master */ }
pub enum DataKind { Str, Num, Currency(Iso4217), Date, Duration, Bool, FixedList(Vec<String>), VarList(Vec<String>) }
pub struct DataSource { pub id: Ulid, pub kind: SourceKind /* Sheets{path, sheet, range} | Xlsx{..} | Csv{path, delimiter} | Base{db, table|query} */, pub columns: Vec<Column>, pub key: Vec<usize>, pub refresh: RefreshPolicy, pub cache: Ulid /* data/cache-*.msx */ }
pub struct DataLink { pub source: Ulid, pub key: DataValue, pub last_sync: DateTime, pub state: LinkState /* Linked | Changed | Missing */ }
pub struct DataGraphic { pub rules: Vec<DataRule>, pub legend: bool }
pub enum DataRule { Text { field, pos: GraphicPos, style }, Icons { field, set: IconSet, thresholds: Vec<(Cmp, DataValue)>, pos }, FillByValue { field, scale: ColorScale }, Bar { field, min, max, pos } }4.5 Трафарет как документ-библиотека
Трафарет — Document { role: Stencil }: страницы не
используются, masters — содержимое,
stencil.xml — порядок, группы, «быстрые фигуры». Открытый
трафарет живёт в панели DR-10; вставка на холст копирует мастер в
Document.masters документа (если такого
(origin, version) ещё нет) и создаёт узел с
MasterRef. Изменение мастера в трафарете не меняет
документы автоматически; «Обновить из трафарета» сравнивает версии.
Экземпляр хранит только Overrides (изменённые свойства) —
размер, трансформация, текст, данные, стиль; геометрия и точки
приклеивания берутся из мастера (при formulas —
пересчитываются по размеру экземпляра, §5.14).
5. Алгоритмы
5.1 Ортогональная маршрутизация коннекторов
Вход: страница, коннектор с портами
Port { pos, dir: Option<Dir> } (направление — из
точки приклеивания или Auto), набор препятствий (bbox
видимых узлов на слоях с snappable, кроме источника/цели и
фигур, помеченных «не обходить»),
RoutingOptions { shape_margin, line_gap, bend_penalty, crossing_penalty, stub_len, avoid_shapes }.
Шаг 1 — ортогональный граф видимости (OVG).
Интересные координаты: для каждого препятствия
x0−m, x1+m, y0−m, y1+m (m = shape_margin), для
портов — их координаты и точка «отступа»
pos + dir·stub_len. Через каждую интересную x
проводится вертикальная линия, через каждую y —
горизонтальная; линии обрезаются препятствиями (sweep line по
отсортированным событиям, O((n + k) log n)). Узлы графа —
пересечения оставшихся отрезков, рёбра — соседние узлы на одном отрезке.
Для страницы с 2 000 фигур граф ≈ 10⁵ узлов; при маршрутизации одного
коннектора область ограничивается прямоугольником портов, расширенным на
2 × наибольшую сторону препятствий (разворачивается до всей страницы,
если путь не найден).
Шаг 2 — поиск A*. Состояние —
(узел, направление входа), стоимость перехода:
len + bend_penalty·[поворот] + crossing_penalty·crossings(ребро) + overlap_penalty·[совпадает с чужим сегментом];
эвристика — манхэттенское расстояние +
bend_penalty·min_bends(узел → цель) (0, если на одной линии
с портом и направление совпадает, иначе 1 или 2) — допустимая. Первый
шаг — обязательно в направлении порта (stub); последний —
вход в порт цели против его направления.
// kernel/crates/meridian-route/src/orthogonal.rs
pub fn route(ovg: &Ovg, src: Port, dst: Port, opt: &RoutingOptions, others: &SegmentIndex) -> Option<Vec<Point>> {
let start = ovg.node_at(src.stub_point(opt.stub_len))?; let goal = ovg.node_at(dst.stub_point(opt.stub_len))?;
let mut open = BinaryHeap::new(); let mut best: HashMap<(NodeIx, Dir), f64> = HashMap::new(); let mut came: HashMap<(NodeIx, Dir), (NodeIx, Dir)> = HashMap::new();
open.push(State { f: h(ovg, start, goal, opt), g: 0.0, node: start, dir: src.dir_or_auto() });
while let Some(s) = open.pop() {
if s.node == goal { return Some(rebuild(&came, (s.node, s.dir), start, &src, &dst)); }
if best.get(&(s.node, s.dir)).is_some_and(|&g| g < s.g) { continue; }
for (next, dir, len) in ovg.neighbors(s.node) {
let bend = if dir != s.dir { opt.bend_penalty } else { 0.0 };
let cross = opt.crossing_penalty * others.crossings(ovg.segment(s.node, next)) as f64;
let overlap = if others.overlaps(ovg.segment(s.node, next)) { opt.overlap_penalty } else { 0.0 };
let g = s.g + len + bend + cross + overlap;
if best.get(&(next, dir)).map_or(true, |&old| g < old) {
best.insert((next, dir), g); came.insert((next, dir), (s.node, s.dir));
open.push(State { f: g + h(ovg, next, goal, opt), g, node: next, dir });
}
}
}
None // резерв: простой маршрут без обхода / fallback: simple route ignoring obstacles
}Шаг 3 — пост-обработка. Удаление коллинеарных
вершин; nudging: все сегменты всех коннекторов
группируются по каналам (горизонтальный канал = интервал между соседними
препятствиями по y), внутри канала сегменты упорядочиваются
так, чтобы их концы не создавали новых пересечений (сортировка по
положению предыдущего/следующего сегмента), затем раскладываются с шагом
line_gap симметрично относительно центра канала; одиночный
сегмент — по центру канала. Скругление углов
(corner_radius) и перекрёстки (дуги радиуса
jump_size в точках пересечения с коннекторами выше по z)
применяются при построении BezPath.
Шаг 4 — инкрементальность. Препятствия — в
RTree страницы. При изменении узла грязная область
dirty = old_bbox ∪ new_bbox (с m).
Пересчитываются: коннекторы, приклеенные к узлу (всегда), и коннекторы,
чей path.bbox пересекает dirty. Во время
перетаскивания — «быстрый режим»: только приклеенные коннекторы, маршрут
Z/L-образный без обхода (< 0,1 мс), на каждом кадре. После отпускания
(или через 60 мс простоя) — полный пересчёт в фоновом потоке
(rayon) со снимком препятствий и ревизией страницы;
результат применяется, если ревизия не изменилась, иначе отбрасывается и
запускается заново. OVG кэшируется и обновляется локально (линии только
в dirty).
Ручные ограничения.
Waypoint::Fixed { axis: Y, value } требует, чтобы один
горизонтальный сегмент лежал на y = value: маршрут ищется
как два A*-прохода (порт → точка на линии, точка → порт) с перебором
узлов OVG на этой линии в пределах окна; Waypoint::Point —
обязательная вершина.
5.2 Прямые и кривые коннекторы
Прямой: отрезок между портами; при Dynamic конце — точка
пересечения луча (центр цели → центр источника) с контуром цели
(kurbo пересечение луча с BezPath по
сегментам), чтобы линия заканчивалась на границе фигуры. Кривой:
кубическая Безье P1 = P0 + d0·k·L,
P2 = P3 − d3·k·L, где d — единичные
направления портов (при Auto — по относительному положению:
горизонтальное, если |Δx| ≥ |Δy|),
L = |P3 − P0|, k = 0,4; при ручной правке —
рукоятки редактируются как узлы Безье и запоминаются в
waypoints.
5.3 Привязка и умные направляющие
Кандидаты (как в Slides §5.3) расширены: вершины и середины сегментов
контуров, центры, точки приклеивания, пересечения направляющих,
продолжения сторон (линии через стороны соседних фигур), сетка с
динамическим шагом step = {1, 2, 5}·10ⁿ единиц чертежа
такой, что step·zoom ≥ 12 px. Радиус привязки
tol = 6 px / zoom, приоритет: точки приклеивания (при
перетаскивании конца коннектора; подсветка точки и фигуры) >
геометрия > направляющие > умные линии фигур > равные
интервалы/размеры > сетка. Кандидаты собираются из R-дерева по окну
viewport ∪ bbox(drag) и кэшируются на время операции. При
рисовании линий — угловая привязка:
angle = round(θ / 15°)·15° при Shift.
Подсказка DR-73 показывает Δ и расстояние до ближайшей фигуры по оси
движения.
5.4 Hit-testing
pub fn hit_test(page: &Page, p_world: Point, zoom: f64, mode: Mode) -> Option<Hit> {
let tol = 3.0 / zoom;
// 1. Ручки активного выделения — приоритет / handles of current selection first
if let Some(h) = page.selection_handles().iter().find(|h| h.rect(zoom).contains(p_world)) { return Some(Hit::Handle(h.kind, h.index)); }
// 2. Кандидаты из R-дерева, обход в обратном z-порядке / candidates from R-tree, top-most first
for id in page.index.locate_at(p_world).sorted_by_z_desc() {
let node = &page.nodes[id];
if !page.layer_hittable(node) { continue; }
let inv = page.world_transform(id).inverse();
let p = inv * p_world;
let hit = match &node.kind {
NodeKind::Group { children, .. } => children.iter().rev().find_map(|c| hit_test_node(page, *c, p, tol)),
NodeKind::Connector(c) => (c.path.nearest_distance(p_world) <= tol.max(c.line_width() / 2.0)).then(|| Hit::Connector(id, c.path.segment_at(p_world))),
_ => hit_test_node(page, id, p, tol),
};
if hit.is_some() { return hit; }
}
None
}
fn hit_test_node(page: &Page, id: NodeId, p: Point /* локальные */, tol: f64) -> Option<Hit> {
let node = &page.nodes[id];
let paths = page.geometry_cache(id); // Vec<(BezPath, PathStyle)> в локальных координатах
if let Some(tb) = node.text_block_rect() { if tb.contains(p) && node.has_text() { return Some(Hit::Text(id)); } }
for (path, st) in paths {
if st.fill != PathFill::None && node.has_fill() && path.winding(p) != 0 { return Some(Hit::Body(id)); } // nonzero
let w = if st.stroke { node.line_width() / 2.0 } else { 0.0 };
if path.segments().any(|seg| seg.bounding_box().inflate(w + tol, w + tol).contains(p) && seg.nearest(p, 1e-3).distance_sq <= (w + tol).powi(2)) { return Some(Hit::Outline(id)); }
}
if node.has_fill_none_but_clickable() && node.local_box().contains(p) && page.option_click_transparent() { return Some(Hit::Body(id)); }
None
}Режим редактирования узлов проверяет сначала узлы и рукоятки (радиус
5 px), затем сегменты (для добавления узла двойным щелчком — ближайшая
t). Выделение рамкой — пересечение/вхождение bbox (с учётом
поворота — по контуру при Alt), лассо — точка-в-полигоне
для центров либо пересечение контуров.
5.5 Булевы операции над контурами
Конвейер
meridian-geom::boolean(op, a: &[BezPath], b: &[BezPath]) -> Vec<BezPath>:
- Контуры приводятся в мировые координаты (аффинная трансформация точек Безье точна).
- Флаттенинг каждого сегмента с допуском
ε = 0,005 мм(kurbo::flatten), каждая точка помечается(contour, segment, t)— происхождение. - Полигональная операция — алгоритм
Мартинеса–Руэды–Фейто (sweep line с событиями пересечения; устойчив к
самопересечениям, касаниям и совпадающим рёбрам; поддерживает
union/intersection/difference/xor;
O((n+k) log n)). Реализация своя (вmeridian-geom), с арифметикой вf64после нормализации координат в единичный квадрат и «снапом» точек пересечения к сетке2⁻³⁰; альтернатива для оценки на фазе прототипа — крейтi_overlay(целочисленный, устойчивый). Выбор фиксируется по результатам фаззинга (10⁶ случайных пар контуров без паник и с корректной площадью ± 10⁻⁶). - Восстановление кривых: цепочки точек результата,
происходящие из одного исходного сегмента (одинаковые
(contour, segment), монотонныеt), заменяются точной подкривойsegment.subsegment(t_a..t_b); точки пересечения уточняются решениемcurve_curve_intersections(kurbo) в окрестности приближённой точки. Участки, собранные из разных сегментов (не бывает при корректной операции, но бывает при снапе), подгоняются алгоритмом Шнайдера (§5.8). - Правило заливки результата — nonzero; ориентация внешних контуров — по часовой, отверстий — против.
«Разделить» = все грани планарного разбиения (xor +
intersection всех пар с помощью той же развёртки — одна
операция «overlay», возвращающая грани с метками принадлежности).
«Обрезать» — разбиение открытых путей в точках пересечения (без
заливки). Стиль результата — верхней фигуры; текст — верхней; данные —
объединение полей.
5.6 Слоистая раскладка (Sugiyama)
// kernel/crates/meridian-graph-layout/src/sugiyama.rs
pub fn layout(g: &Graph, sizes: &[Size], o: &LayeredOptions) -> Vec<Point> {
// 1. Удаление циклов: DFS, обратные рёбра переворачиваются (эвристика Eades–Lin–Smyth для плотных графов)
let (dag, reversed) = break_cycles(g);
// 2. Слои: longest-path, затем уплотнение сетевым симплексом (Gansner) при n ≤ 2000, иначе — Coffman–Graham с лимитом ширины
let mut layers = assign_layers(&dag, o.width_limit);
// 3. Длинные рёбра → цепочки фиктивных узлов / long edges → dummy node chains
let (dag2, dummies) = insert_dummies(&dag, &mut layers);
// 4. Минимизация пересечений: 24 прохода вниз/вверх медианной эвристикой + transpose, лучший результат сохраняется
let order = minimize_crossings(&dag2, &layers, 24);
// 5. Координаты: Brandes–Köpf (4 выравнивания, медиана) — прямые длинные рёбра, компактность
let xs = brandes_koepf(&dag2, &layers, &order, sizes, o.node_gap);
let ys = layer_positions(&layers, sizes, o.layer_gap); // с учётом максимальной высоты в слое
// 6. Удаление фиктивных узлов: их координаты → точки маршрута рёбер; обратные рёбра — восстановление направления
finalize(xs, ys, dummies, reversed, o.direction) // поворот для LR/BT/RL
}Коннекторы после раскладки — ортогональные с портами «низ → верх» (по
направлению), маршрутизация §5.1 с готовыми точками фиктивных узлов как
Waypoint::Point (убирает лишние обходы). Сохранение порядка
пользователя: начальный порядок в слоях — по текущим x
(если раскладка повторная). Группы и контейнеры — как один узел (размер
контейнера), внутри — рекурсивная раскладка.
5.7 Деревья, круговая, радиальная, mind map, силовая
- Дерево (Walker, в формулировке Buchheim–Jünger–Leipert,
O(n)): предварительные
xснизу вверх с «нитями» для контуров поддеревьев, смещенияmod, второй проход сверху вниз; интервалыnode_gap,level_gap; варианты для организационных диаграмм: «по сторонам» (дети в ряд), «вертикально» (дети колонкой под родителем со смещением — колонка занимает одну единицу ширины), «помощники» (отдельный слой между родителем и детьми, слева/справа от линии). - Круговая: узлы на окружности
R = max(n·(d + gap) / 2π, R_min); порядок — по барицентру соседей (3 итерации) для уменьшения пересечений хорд; связные компоненты — отдельные круги, упакованные по спирали. - Радиальная: BFS от корня (или центра графа — узел
минимального эксцентриситета); уровень
k— окружность радиусаk·level_gap; угловые секторы распределяются пропорционально числу листьев поддерева; узлы размещаются в середине сектора; при переполнении окружности радиус увеличивается. - Mind map: корень в центре; дети делятся на правую и левую группы жадно по суммарной высоте поддеревьев (балансировка); каждая сторона — Walker с горизонтальной ориентацией; коннекторы — кривые (Безье) из правой/левой точки приклеивания; цвет ветви наследуется.
- Силовая (P1): Fruchterman–Reingold,
k = C·√(area/n), 300 итераций с охлаждением, Barnes–Hut (θ = 0,8) приn > 500, отталкивание с учётом размеров узлов (расстояние между bbox), фиксированные узлы по выбору пользователя, начальное положение — текущее.
5.8 Упрощение контуров и подгонка кривых
Карандаш: входные точки (с давлением) → Ramer–Douglas–Peucker с
ε = 0,75 px / zoom → подгонка кубическими Безье по Шнайдеру
(Graphics Gems, 1990): касательные на концах по соседним точкам,
параметризация по хордам, подбор коэффициентов методом наименьших
квадратов, оценка ошибки, при превышении
ε_fit = 1,5 px / zoom — переразбиение в точке максимальной
ошибки (рекурсивно, с перепараметризацией Ньютона–Рафсона до 4
итераций). Узлы результата — «гладкие». Команда «Упростить» для
существующих кривых: флаттенинг → RDP → Шнайдер; ползунок допуска с
предпросмотром. Для сглаживания штрихов в реальном времени — Catmull-Rom
по последним 4 точкам (как в Notes).
5.9 Текст по пути
- Раскладка текста движком
text-layoutв бесконечную строку → глифы с позициямиx_i, ширинамиadv_i. - Параметризация пути по длине дуги
(
kurbo::ParamCurveArclen):L = len(path); стартовое смещениеs0 = start_offset + align(L − text_width)(Start → 0,Center → (L − w)/2,End → L − w). - Для глифа
i: центрs_i = s0 + x_i + adv_i/2;t = inv_arclen(s_i); точкаP = path.eval(t), касательнаяT = path.deriv(t).normalize(), нормальN = T.rot90()·side; глиф ставится вP + N·(baseline_offset)с поворотомatan2(T.y, T.x), якорь — середина advance. - Глифы с
s_i > L(текст длиннее пути) не рисуются; в режиме «замкнутый путь» — продолжают по кругу (s mod L). - Для рендера текст превращается в контуры глифов (
SkPathизfont.getPath) с трансформацией — так же экспортируется в SVG (<textPath>) и PDF (как текст с матрицами глифов, с сохранением извлекаемости).
5.10 Контейнеры и списки
Членство: при отпускании перетаскиваемых узлов — для каждого
контейнера под курсором (сверху вниз) проверка «центр узла внутри тела
контейнера» (или ≥ 50 % площади по настройке); при входе —
base.container = Some(c), при выходе — None.
Перемещение контейнера применяет ту же Δ ко всем членам
(одной транзакцией undo); удаление — с членами (по подтверждению).
Авторазмер: AlwaysFit — после каждой операции над членами
bbox(members) + padding → размер контейнера (только рост
при OnDrop). Список: члены упорядочены; при вставке
вычисляется индекс по положению курсора вдоль оси списка; все члены
перекладываются: pos_i = start + Σ_{j<i}(size_j + gap) с
выравниванием по второй оси; при перетаскивании над списком показывается
«место вставки» (оранжевая линия --m-sun), остальные члены
раздвигаются (анимация 120 мс). Дорожки: пул — список
контейнеров-дорожек; изменение ширины дорожки сдвигает последующие; фазы
— вертикальные разделители пула с собственными заголовками. Коннекторы,
входящие в контейнер, маршрутизируются с контейнером как препятствием
только если «обходить контейнеры» включено (по умолчанию выключено —
коннекторы входят внутрь).
5.11 Связывание с данными
pub fn refresh(doc: &mut Document, src_id: Ulid) -> RefreshReport {
let src = doc.data_source(src_id);
let rows = src.read()?; // Sheets/CSV/xlsx/Base через кодеки
let key_of = |r: &Row| src.key.iter().map(|&i| r[i].clone()).collect::<Vec<_>>();
let mut by_key: HashMap<Vec<DataValue>, &Row> = rows.iter().map(|r| (key_of(r), r)).collect();
let mut report = RefreshReport::default();
for page in doc.pages.values_mut() {
for node in page.nodes.values_mut().filter(|n| n.base.data.link.as_ref().is_some_and(|l| l.source == src_id)) {
let link = node.base.data.link.as_mut().unwrap();
match by_key.remove(&link.key) {
Some(row) => { let changed = apply_row(&mut node.base.data, src, row); link.state = if changed { LinkState::Changed } else { LinkState::Linked }; report.updated += changed as usize; }
None => { link.state = LinkState::Missing; report.missing += 1; } // строка удалена / row removed
}
}
}
report.new_rows = by_key.into_keys().collect(); // строки без фигур → «создать фигуры» / unlinked rows
doc.update_cache(src_id, &rows); // data/cache-<ulid>.msx для офлайн-открытия
report
}Политика конфликтов: поле, изменённое вручную после последней синхронизации (отметка времени на поле), при расхождении со строкой — вопрос пользователю (применить внешнее / оставить своё / для всех). «Автосвязь» — сопоставление по равенству значения поля фигуры и столбца-ключа. «Создать фигуры из строк» — мастер по умолчанию трафарета, раскладка §5.6/§5.7 при наличии столбца «родитель» (организационная диаграмма из таблицы: столбцы «Имя», «Руководитель», «Должность»).
5.12 Размерные линии
Dimension { kind, anchors: [Anchor; 2] /* Anchor = Free(Point) | NodePoint { node, point: GeomPointRef } */, offset, text_override, style }.
Значение: v = |P2 − P1| · scale (линейный — проекция на
ось), угловой — угол между лучами, радиус — от центра дуги (определяется
по трём точкам контура). Геометрия размерной фигуры — параметрический
контур (как custGeom с направляющими: выносные линии от
якорей на offset, размерная линия, стрелки, текст по центру
с зазором). Якоря NodePoint обновляются по событию
изменения узла (подписка через индекс зависимостей
node → dimensions). Текст — формат
{value:0.0} мм с единицами чертежа,
text_override может содержать <> для
подстановки значения (как в CAD).
5.13 Рендер на Skia с кэшированием
Page → (видимые слои, порядок) → culling по viewport (R-tree) → DisplayList (ядро Meridian Render) → Skia
Кэши:
| Кэш | Ключ | Содержимое | Инвалидация |
|---|---|---|---|
| Геометрия | (NodeId, size, adj, geom_rev) |
Vec<(SkPath, PathStyle)> в локальных
координатах |
изменение геометрии/размера |
| Раскладка текста | (NodeId, text_rev, width) |
TextLayout (глифы, строки) |
текст/стиль/ширина блока |
| Растр узла | (NodeId, zoom_bucket, node_rev) |
SkImage узла с эффектами (тени, размытия, изображения,
большие группы > 200 детей) |
изменение узла; zoom_bucket = round(log2 zoom · 2) —
перерисовка при изменении масштаба более чем на √2 |
| Тайлы холста | (page, zoom_bucket, tile_x, tile_y) |
SkImage 512×512 для страниц > 5 000 узлов («режим
карты») |
dirty-rect → пересчёт затронутых тайлов |
| Маршруты | Connector.path_rev |
BezPath маршрута |
§5.1 |
Dirty-rect: каждая операция ставит в очередь
old_bbox ∪ new_bbox (мировые, с учётом эффектов — тень
расширяет bbox на blur·3 + distance); кадр перерисовывает
объединение прямоугольников через canvas.clipRect.
Интерактивный слой (выделение, ручки, направляющие, «резиновый» маршрут
при перетаскивании, подсказки) — отдельный QQuickItem
поверх холста, не инвалидирует документ-слой. При
панорамировании/масштабировании со скоростью > 1 экран/с —
прогрессивный рендер: сначала кэшированные тайлы/растры с билинейным
масштабированием, затем полная перерисовка через 80 мс простоя. Цель: 60
к/с при 10 000 фигур на странице при панорамировании, 60 к/с при
перетаскивании фигуры с 50 коннекторами.
5.14 Подмножество формул ShapeSheet при импорте vsdx
Каждая ячейка vsdx имеет значение V и формулу
F. Отображение строится по V (точно). Для
«живого» поведения экземпляра (регуляторы, изменение размера с
сохранением частей) интерпретируется подмножество F:
операторы + − * / ^ & = <> < >, функции
Width Height PinX PinY LocPinX LocPinY Angle FlipX FlipY TxtWidth TxtHeight,
MIN MAX ABS SQRT SIN COS TAN ATAN2 PI INT ROUND MOD IF AND OR NOT GUARD SETATREF (игнор),
ссылки Scratch.X1.., User.*,
Prop.*, Controls.Row_N,
Connections.X1, Geometry1.X1,
ThePage!PageWidth, TheDoc!DocLangID
(константа). Неподдерживаемые формулы (CALLTHIS,
DEPENDSON, SETF, ссылки на другие фигуры
Sheet.N!) — ячейка «замораживается» на V.
Результат — FormulaSet мастера (§4.2); вычисление —
топологическая сортировка зависимостей, пересчёт при изменении
размера/регулятора (~ 50–300 ячеек на мастер, < 50 мкс).
6. MeridianScript API для Draw
Пространство имён meridian.draw. Одна скриптовая
транзакция — один шаг отмены.
| Объект | Основные члены |
|---|---|
draw.activeDocument: Document |
pages, masters, stencils
(открытые), styles, theme, units,
dataSources, save(),
saveAs(path, format?), export(format, opts),
print(opts) |
PageCollection / Page |
add(name, opts?), byName,
item(i); Page: name,
size, scale, background,
layers: LayerCollection,
nodes: NodeCollection, guides,
routing: RoutingOptions, layout(kind, opts),
fitToContent(), thumbnail(width),
export(format, opts) |
LayerCollection / Layer |
add(name), byName; Layer:
name, visible, locked,
printable, snappable, color,
opacity, nodes |
NodeCollection |
count, item, byName,
byId, select(filter),
addShape(preset | masterRef, rect),
drop(master, point), addLine(p1, p2),
addPath(svgPath, opts), addText(rect, text),
addTextOnPath(path, text),
addImage(src, rect),
addConnector(from, to, opts),
addContainer(rect, opts),
addDimension(kind, p1, p2), group(nodes),
boolean(op, nodes) |
Node (общее) |
id, name, type,
layers, bounds, position,
size, angle, transform,
fill, line, effects,
text: TextFrame, data: ShapeData,
master?, gluePoints, hyperlinks,
locks, container?, connectors
(входящие/исходящие), connectedNodes(dir),
moveTo, resize, rotate,
bringToFront, sendToBack,
duplicate, delete,
replaceWith(master) |
Connector |
routing, begin: { node?, point? },
end, glue(node, point?),
unglue(end), waypoints,
reroute(), reset(), markers,
labels, path: string (SVG) |
ShapeData |
get(name), set(name, value),
fields: DataField[], define(field),
link: DataLink?, linkTo(source, key) |
DataSource |
refresh(), rows, columns,
key, createShapes(master, opts),
on('refresh', cb) |
Master / Stencil |
Stencil.open(path), stencil.masters,
master.name, master.drop(page, point),
master.updateInstances(),
Document.saveAsMaster(node, stencil, opts) |
draw.layout |
layered(nodes, opts), tree(root, opts),
circular, radial, mindMap,
force (P1) |
draw.geom |
boolean(op, paths), simplify(path, tol),
offset(path, d), intersect(path1, path2),
pathLength, pointAt(path, t) |
draw.ui |
selection: Node[], activePage,
zoom, scrollTo, showPanel(id),
toast, dialog |
draw.events |
on('nodeAdded' | 'nodeChanged' | 'connected' | 'dataChanged' | 'pageChanged' | 'beforeSave', cb) |
// Организационная диаграмма из таблицы Sheets / Org chart from a Sheets table
import { sheets, draw } from "meridian";
const rows = (await sheets.open("Сотрудники.msx")).sheet("Штат").range("A2:C200").values as [string, string, string][];
const doc = draw.activeDocument;
const page = doc.pages.add("Структура");
const stencil = await draw.Stencil.open("builtin:orgchart");
const byName = new Map<string, draw.Node>();
for (const [name, manager, title] of rows) {
const n = stencil.masters.byName("Должность").drop(page, { x: 0, y: 0 });
n.text.text = `${name}\n${title}`;
n.data.set("Руководитель", manager);
byName.set(name, n);
}
for (const [name, manager] of rows) if (byName.has(manager)) page.nodes.addConnector(byName.get(manager)!, byName.get(name)!, { routing: "orthogonal" });
draw.layout.tree(byName.get(rows[0][0])!, { direction: "down", levelGap: 20, nodeGap: 10, units: "mm" });
page.fitToContent();// Экспорт всех страниц в SVG и PNG / Export every page to SVG and PNG
for (const p of draw.activeDocument.pages) {
await p.export("svg", { path: `out/${p.name}.svg`, textAsPaths: false, layersAsGroups: true });
await p.export("png", { path: `out/${p.name}.png`, dpi: 200, transparent: true });
}// Перекраска сетевых устройств по данным и перемаршрутизация / Recolor by data and reroute
const page = draw.ui.activePage;
for (const n of page.nodes.select(n => n.master?.stencil === "network" && n.data.get("Статус") === "down")) n.fill = { color: "#C92A2A" };
for (const c of page.nodes.select(n => n.type === "connector")) (c as draw.Connector).reroute();7. Форматы
7.1 .mvx
См. §4.1. Плоский .mvxf — один XML с теми же элементами
и медиа в base64 (для git-диффов). Шаблон .mvt — пакет с
ролью template. Трафарет — пакет с ролью
stencil (расширение — см. §11).
7.2 SVG
Чтение:
svg/g/path/rect/circle/ellipse/line/polyline/polygon/text/tspan/textPath/image/use/symbol/defs/linearGradient/ radialGradient/pattern/clipPath/mask/marker/style (CSS-подмножество: селекторы по тегу/классу/id, свойства представления),
transform, viewBox, единицы; фильтры
feGaussianBlur, feDropShadow → эффекты; прочие
фильтры — растрируются (resvg) как изображение-резерв.
Группы → группы; id/class → имя/теги; слои
Inkscape (inkscape:groupmode="layer") → слои. Запись:
страница → <svg viewBox> в мм; слои →
<g data-m-layer="…">; фигуры →
<path> (prstGeom разворачивается в путь) с
data-m-preset/data-m-adj для обратного
импорта; текст → <text> с font-family и
резервом; коннекторы → <path> с маркерами
<marker>; данные фигур →
<metadata> (пространство имён
urn:meridian:office:draw:1) при включённой опции;
изображения — встроенные data: или ссылки.
7.3 VSDX (чтение P0, запись P1
[Pro])
OPC-пакет: visio/document.xml (стили, цвета, шрифты,
DocumentSheet), visio/pages/pages.xml +
pageN.xml (PageSheet:
PageWidth/PageHeight/DrawingScale/PageScale/DrawingSizeType/ShdwOffsetX…/PageLineJumpDirX/LineJumpStyle/ LineRouteExt/RouteStyle/AvoidPageBreaks),
Shapes/Shape (Type=Shape|Group|Guide|Foreign,
Master, MasterShape, ячейки
PinX/PinY/Width/Height/LocPinX/LocPinY/Angle/FlipX/FlipY/BeginX…EndY,
секции Geometry
(MoveTo LineTo ArcTo EllipticalArcTo Ellipse InfiniteLine NURBSTo SplineStart SplineKnot PolylineTo RelMoveTo RelLineTo RelCubBezTo RelQuadBezTo RelEllipticalArcTo
→ BezPath; NURBS → аппроксимация кубиками;
NoFill/NoLine/NoShow),
Character/Paragraph/Tabs/ TextBlock/TextXForm,
Text с cp/pp/tp/fld, Connection
(точки приклеивания X/Y/DirX/DirY/Type/AutoGen),
Controls, Property (Prop.*:
Label/Prompt/Type/Format/Value/SortKey/Invisible),
User, Layer/LayerMember,
Hyperlink, Protection, Actions
(игнор), Connects/Connect
(FromSheet/FromCell/ToSheet/ToCell/FromPart/ToPart),
visio/masters/masters.xml + masterN.xml
(наследование ячеек: пустая ячейка экземпляра = значение мастера —
слияние при чтении), visio/theme/themeN.xml + ячейки
QuickStyle*, visio/data/
(DataConnection, DataRecordSet,
connections.xml, recordsets.xml →
DataSource + кэш), comments.xml,
windows.xml, validation.xml (P2),
solutions/ (round-trip), media/. Единицы —
дюймы (DrawingScale/PageScale); все координаты
переводятся в мм. Запись (подмножество): страницы, фигуры с геометрией
Geometry (из наших контуров), текст, стили, слои,
коннекторы с Connect, данные Prop.*, мастера
документа; формулы — только тривиальные (Width*0.5) для
точек приклеивания.
| Трудности vsdx | Решение |
|---|---|
| Наследование ячеек мастер → экземпляр, тема → стиль → ячейка | трёхуровневое слияние при чтении, запись явных значений |
| Формулы ShapeSheet | §5.14; при экспорте — значения |
Текстовые поля fld с формулами (=Prop.X,
даты, формат) |
сопоставление с нашими полями; неизвестные — текст по
V |
EllipticalArcTo (параметры: точка, контрольная точка,
угол, отношение осей) |
перевод в дугу через центр/радиусы (решение системы) → кубики |
Группы с Group + собственная геометрия + текст |
наш Group + «фигура-обёртка» с геометрией (как
Visio) |
Line jumps, LineRouteExt,
ShapeRouteStyle |
параметры страницы/коннектора |
Темы Visio (themeN.xml отличается от DrawingML:
a:theme + vt: расширения) |
импорт цветовой схемы/шрифтов, vt: — стили
коннекторов/эффекты |
Фигуры-«иностранцы» (Foreign: EMF/растр, OLE) |
изображение + round-trip |
7.4 VSD (бинарный, P1)
OLE2: поток VisioDocument (заголовок, таблица указателей
на «chunks»: Shape, Page, Master,
Text, Geometry, XForm,
Line, Fill, Para,
Char, Connect, Layer,
Prop), сжатие LZ-подобное у части потоков, кодировки текста
(UTF-16/ANSI), Visio 6 (2000/2002) и 11 (2003–2010) различаются
структурами. Ориентир — поведение libvisio (MPL, не
линкуем, собственная реализация на Rust). Чтение: страницы, мастера,
фигуры (геометрия, стили, текст), коннекторы, слои, данные. Запись не
планируется.
7.5 drawio
mxfile/diagram (несколько страниц; содержимое —
mxGraphModel в открытом XML либо deflate + base64 +
URL-encoding), mxCell
(vertex/edge, parent для
групп/слоёв — слой = дочерний mxCell корня 1),
mxGeometry (x y width height,
relative, sourcePoint/targetPoint,
points — маршрут), style — строка
key=value;… (shape=, rounded,
whiteSpace, html, fillColor,
strokeColor, strokeWidth, dashed,
fontSize, fontFamily, align,
verticalAlign,
edgeStyle= orthogonalEdgeStyle|elbowEdgeStyle|entityRelationEdgeStyle,
startArrow/endArrow, exitX/exitY/entryX/entryY
— точки приклеивания, image=,
shape=mxgraph.<lib>.<name>), value
— HTML-разметка текста (подмножество → наш текст),
UserObject с атрибутами → данные фигур. Сопоставление
shape= → наши мастера: таблица для flowchart,
basic, bpmn, uml,
er, network/cisco,
office,
mscae/aws*/gcp*/azure
(при наличии пакетов), electrical, floorplan,
mockup, lean_mapping, sysml
(частично); неизвестные — ближайшая базовая фигура + сохранение
исходного style для экспорта обратно; встроенные
image=data: — изображения. Экспорт (P1): обратная таблица,
наши prstGeom → shape= draw.io, маршруты
коннекторов → points.
7.6 DXF
Секции HEADER ($INSUNITS,
$EXTMIN/$EXTMAX, $DIMSTYLE),
TABLES (LAYER, LTYPE,
STYLE, DIMSTYLE, BLOCK_RECORD),
BLOCKS, ENTITIES (LINE,
LWPOLYLINE с выпуклостью bulge → дуги,
POLYLINE/VERTEX, CIRCLE, ARC,
ELLIPSE, SPLINE (NURBS → кубики),
TEXT, MTEXT (форматные коды
\P \f \H \C — подмножество), INSERT (блоки →
мастера/группы, масштаб/поворот/массивы), DIMENSION (из
блока *D → группа линий + наша размерная линия при
распознавании типа), HATCH (сплошная и простые паттерны
ANSI31… → штриховки), SOLID, POINT,
ATTRIB/ATTDEF → данные фигур), цвета ACI (256) и
TrueColor, толщины, типы линий (DASHED и т.д.
→ штрихи), слои с OFF/FROZEN/LOCKED. Единицы по
$INSUNITS, размер страницы по экстенту. Экспорт (P1):
LWPOLYLINE/SPLINE/TEXT/LAYER/блоки
из мастеров, версия AC1015 (2000) для совместимости.
7.7 EMF/WMF, ODG, CDR
EMF — записи GDI (EMR_POLYBEZIER*,
EMR_POLYLINE*, EMR_RECTANGLE,
EMR_ELLIPSE, EMR_ARC*,
EMR_EXTTEXTOUTW, EMR_BITBLT/STRETCHDIBITS,
пути BEGINPATH..ENDPATH, трансформации
SETWORLDTRANSFORM, перья/кисти/шрифты; EMF+ (GDI+ записи
внутри EMR_COMMENT) — базовые примитивы, остальные через
GDI-дубли); WMF — 16-битные аналоги; запись EMF — собственный писатель
(кроссплатформенный) для буфера обмена Windows и экспорта. ODG — ODF
Drawing (draw:page, draw:layer-set,
draw:custom-shape+draw:enhanced-geometry,
draw:connector с draw:type
line/lines/curve/standard и точками приклеивания
draw:glue-point, draw:measure размерные линии,
draw:text-box, draw:frame/draw:image,
svg: атрибуты) — полное чтение/запись; трафареты — как
draw:page с мастерами в отдельном .odg. CDR
(P2) — RIFF-контейнер, подмножество версий X4–2021 (кривые, заливки,
текст, страницы) по образцу libcdr.
8. Горячие клавиши
Схема по умолчанию: инструменты — как в Visio
(Ctrl+цифра), остальное — общие соглашения пакета (см.
docs/apps/slides.md §8).
| Действие | Клавиши |
|---|---|
| Инструменты: указатель / текст / коннектор / точка приклеивания | Ctrl+1 / Ctrl+2 / Ctrl+3 /
Ctrl+Shift+1 |
| Перо (кривая; на выделенной фигуре — режим узлов) / карандаш / линия / дуга / прямоугольник / эллипс | Ctrl+4 / Ctrl+5 / Ctrl+6 /
Ctrl+7 / Ctrl+8 / Ctrl+9 |
| Обрезка рисунка | Ctrl+Shift+4 |
| Командная палитра / гиперссылка | Ctrl+K / Ctrl+Shift+K (см.
docs/apps/slides.md §11) |
| Дублировать / дублировать с повтором последнего смещения | Ctrl+D / Ctrl+Shift+D |
| Группировать / разгруппировать / войти в группу / выйти из группы | Ctrl+G / Ctrl+Shift+U /
Ctrl+Enter / Esc |
| На передний / на задний план | Ctrl+Shift+F / Ctrl+Shift+B |
| Вперёд / назад на один уровень | Ctrl+Alt+] / Ctrl+Alt+[ |
| Повернуть на 90° влево / вправо | Ctrl+L / Ctrl+R |
| Отразить по горизонтали / по вертикали | Ctrl+H / Ctrl+J |
| Выровнять (диалог) / распределить | F8 / Shift+F8 |
| Панель «Размер и положение» | Alt+Shift+P |
| Редактировать текст / завершить | F2 (или двойной клик) / Esc |
| Сдвиг на 1 px / на шаг сетки | ←↑→↓ / Shift+←↑→↓ |
| Изменить размер на 1 px | Ctrl+Shift+←↑→↓ |
| Временно отключить привязку / ограничить угол / рисовать от центра | Alt / Shift / Ctrl (во время
перетаскивания) |
| Соединить выделенные фигуры цепочкой | Alt+Shift+C |
| Перемаршрутизировать коннекторы / сбросить маршрут | Alt+Shift+R / Alt+Shift+Backspace |
| Булевы: объединить / вычесть / пересечь / исключить / разделить | Ctrl+Alt+U / Ctrl+Alt+S /
Ctrl+Alt+I / Ctrl+Alt+X /
Ctrl+Alt+D |
| Слои: панель / новый слой / на слой выше / на слой ниже | Ctrl+Shift+L / Ctrl+Shift+N /
Ctrl+Shift+Page Up / Ctrl+Shift+Page Down |
| Панели: Данные фигуры / Фигуры / Навигатор / Внешние данные | Alt+Shift+D / Alt+Shift+F /
Alt+Shift+N / Alt+Shift+E |
| Сетка / направляющие / линейки / точки приклеивания | Shift+F9 / Alt+F9 /
Ctrl+Shift+R / Alt+Shift+G |
| Масштаб: вписать страницу / вписать всё / 100 % / увеличить / уменьшить | Ctrl+0 / Ctrl+Shift+0 /
Ctrl+Alt+1 / Ctrl++ / Ctrl+− |
| Окно панорамы | Ctrl+Shift+M |
| Панорамирование | Пробел+перетаскивание, средняя кнопка мыши, колесо
(Shift — горизонтально) |
| Страницы: следующая / предыдущая / новая / обзор страниц | Ctrl+Page Down / Ctrl+Page Up /
Ctrl+Shift+Insert / Ctrl+Shift+O |
| Полноэкранный просмотр / выход | F5 / Esc |
| Найти / заменить / выделить по условию | Ctrl+F / Ctrl+Shift+H /
Ctrl+Shift+E |
| Формат по образцу | Ctrl+Shift+P |
| Отменить / повторить / сохранить / печать | Ctrl+Z / Ctrl+Y / Ctrl+S /
Ctrl+P |
| Контекстное меню / подсказки ленты | Shift+F10 / Alt |
Отличия от Office-схемы: Ctrl+H — отражение (как в
Visio), замена — Ctrl+Shift+H;
Ctrl+B/Ctrl+I/Ctrl+U действуют
только в режиме редактирования текста. В схеме «LibreOffice» клавиши
инструментов Ctrl+цифра не назначены.
9. Критерии готовности 1.0
| № | Критерий | Метрика |
|---|---|---|
| 1 | Импорт vsdx | корпус ≥ 2 000 файлов (шаблоны Visio, корпоративные схемы, планы): 100 % открытие без сбоев (фаззинг 72 ч), SSIM ≥ 0,97 для 95 % страниц против Visio; коннекторы приклеены и маршрутизируются |
| 2 | Трафареты | ≥ 20 библиотек, ≥ 900 мастеров, у каждого — точки приклеивания,
подсказка, значок, корректное поведение при изменении размера; импорт
.vssx 100 % |
| 3 | Маршрутизация | на тестовом наборе 500 схем (10–2 000 фигур): 0 пересечений коннекторов с фигурами, медиана изломов ≤ Visio + 10 %, время полного пересчёта 200 коннекторов ≤ 50 мс, при перетаскивании 60 к/с |
| 4 | Булевы операции | 10⁶ случайных пар контуров без паник; площадь результата с погрешностью ≤ 10⁻⁶; кривые сохраняются (не полигонизируются) там, где не было пересечений |
| 5 | Автораскладка | Sugiyama: графы до 2 000 узлов ≤ 1 с; число пересечений не хуже
dagre на эталонных графах (Rome graphs) ±5 %; деревья до 10
000 узлов ≤ 200 мс |
| 6 | Производительность | страница с 10 000 фигур: открытие ≤ 2 с, панорамирование 60 к/с, выделение рамкой ≤ 16 мс; память ≤ 500 МБ |
| 7 | SVG | тест-сьют W3C SVG 1.1 (статика) — ≥ 95 % совпадений с
resvg; экспорт валиден (svgcheck), повторный
импорт нашего SVG без потерь |
| 8 | drawio | корпус 500 файлов: 100 % открытие, стандартные библиотеки — 100 % сопоставление, визуальное совпадение ≥ 0,9 |
| 9 | DXF | корпус 300 файлов (R12–2018): 100 % открытие, слои/блоки/размеры распознаны |
| 10 | Данные | связь с Sheets/CSV/xlsx; обновление 10 000 строк ≤ 1 с; фигуры из строк с раскладкой |
| 11 | Печать/PDF | разбиение на листы с метками; PDF вектор с текстом, PDF/A; гиперссылки |
| 12 | Доступность | скринридеры читают фигуры в порядке чтения, навигация по коннекторам; все команды с клавиатуры |
| 13 | Скрипты | API §6 покрыт тестами; 15 примеров в галерее |
| 14 | Совместимость со Slides/Write | копирование фигур в обе стороны без потерь (общий буфер сцены) |
| 15 | Стабильность | автосохранение/восстановление; парсеры в песочном процессе |
10. Риски
| Риск | Вероятность | Влияние | Снижение |
|---|---|---|---|
| ShapeSheet: тысячи формул в реальных мастерах, «живое» поведение не воспроизводится | высокая | средняя | отображение по V всегда точное; формулы — подмножество;
«заморозка» с предупреждением |
| Качество маршрутизации на плотных схемах (сотни коннекторов в одном канале) | средняя | высокая | nudging по каналам, штрафы, тесты на реальных схемах, ручные ограничения |
| Устойчивость булевых операций (вырожденности, касания) | средняя | средняя | алгоритм Мартинеса + снап; фаззинг; резерв —
i_overlay |
| Лицензии наборов значков (AWS/Azure/GCP, Cisco) | высокая | низкая | не включать в дистрибутив; загружаемые пакеты с принятием лицензии вендора |
Бинарный .vsd — объём реверс-инжиниринга |
высокая | низкая | P1; приоритет vsdx (Visio 2013+ сохраняет vsdx по умолчанию 10+ лет) |
| Производительность Skia на страницах с десятками тысяч фигур и текстов | средняя | средняя | тайлы, растровые кэши, прогрессивный рендер, упрощение при малом масштабе |
| Расхождения SVG-рендера (фильтры, CSS, шрифты) | средняя | низкая | растрирование нераспознанных частей через resvg;
сохранение исходного SVG для экспорта |
| Draw.io «mxgraph.*» фигуры — сотни форм без спецификации | средняя | средняя | таблица сопоставления для топ-200 форм по частоте; остальные — изображения из встроенного SVG-кэша draw.io, если есть |
| Расхождение ожиданий пользователей Visio (ShapeSheet-редактор, Data Visualizer) | средняя | низкая | ShapeSheet-редактор — P2; Data Visualizer — «фигуры из строк» покрывает основной сценарий |
| Объём 1.0 (три сложные подсистемы: маршрутизация, трафареты, данные) | высокая | высокая | строгие P0; vsd, силовая раскладка, validation, C4/wireframes — в 1.x |
11. Вопросы к библии
- Расширение трафарета. В §3.2 библии у Draw только
.mvx/.mvt/.mvxf. Трафарет здесь — пакет.mvxсmanifest.xml/@role="stencil". Предложение: отдельное расширение.mvs(как.vssxу Visio), чтобы трафареты отличались в проводнике и Hub; MIMEapplication/vnd.meridian.draw.stencil. - Free и Draw. Библия включает Draw в Home+. Принято
здесь: в Free документы Draw (
.mvx,.vsdx,.drawio,.svg) открываются для просмотра, печати и экспорта в PDF (принцип «документы никогда не блокируются»), редактирование —Feature::AppDraw. Нужно подтверждение. - Meridian Scene как именованный модуль. Крейт общей
графики сцены (
meridian-scene) используют Write, Sheets, Slides, Draw; предлагается добавить его в таблицу §2.2 библии и завестиdocs/algorithms/scene.md(см. такжеdocs/apps/slides.md§11). - Экспорт vsdx и Pro.
docs/10-licensing-accounts.mdотноситdraw_vsdx_exportк Pro, тогда как библия §3.3 указывает.vsdxв экспорте Draw без оговорок. Нужно решение, как и дляslides_video_export. - Матрица форматов. В §3.3 библии у Draw в чтении нет
.vssx(трафареты Visio) и.odg-трафаретов; предлагается добавить.vssx/.vssmв колонку «Чтение».