Скачать конвертер
Для работы мне необходимы контуры микроорганизмов, которые я использую для сравнения форм. Я получаю контуры из фотографий, очерчивая объект в векторном редакторе. Программа сохраняет результат в СВГ файле, а мне нужны живые координаты точек. Чтобы получить координаты, я анализирую СВГ файл.
СВГ файл состоит из тегов. Я разберу только один — path, — остальные мне не нужны. Он хранит описание криволинейных и замкнутых траекторий. Траектория — это и есть тот самый контур микроорганизма.
Учим синтаксис тега path
Описание траектории вложено в тег svg. Примерно так:
Заголовок подтверждающий, что это СВГ
<svg>
<path ... />
</svg>
Тег path содержит один атрибут d с алгоритмом рисования траектории.
<path d="алгоритм рисования" />
Алгоритм состоит из букв-команд и цифр-координат, которые разделенны пробелом, запятой или знаком минус. Траекторию рисует перо, буквы-команды управляют, цифры-координаты показывают куда или как сместить перо, а разделители отделяют одно от другого.
Разделители разделяют
Пробел — это стандартный разделитель. Его можно ставить везде между командами и координатами. Спецификация СВГ разрешает не писать пробел, когда из контекста понятно, что здесь две разные сущности. Это сокращает объем СВГ-файла.
Запомним:
- пробел не нужен между командой и числом;
- пробел не нужен после запятой;
- пробел не нужен перед знаком минус.
Запятая тоже разделяет два числа, но вместо нее можно написать пробел. Что именно написать — дело вкуса.
Следующие три записи эквивалентны, но последняя компактнее.
<path d="M 15 17 L 18 -23 Z" />
<path d="M 15, 17 L 18, -23 Z" />
<path d="M15,17L18-23Z" />
Теперь о цифрах.
Цифры хранят координаты
СВГ предназначен для хранения двумерной графики. Поэтому цифры задают координаты точек на плоскости. Для каждой точки используется два числа — первое для x, второе для y.
Координаты бывают абсолютными и относительными. Абсолютные координаты отсчитываются от нуля, относительные — от конечной точки предыдущей команды. Относительные — это шаг, на который надо сдвинуть перо относительно последней позиции.
Тип координат определяет регистр буквы-команды: большая буква обозначает абсолютную позицию, маленькая — относительную.
Заглавная буква-команда — для абсолютных координат, прописная — для относительных
Точка является десятичным разделителем вещественных чисел. Запись 12,75 — это два числа: 12 и 75, тогда как 12.75 — это одно вещественное число.
Точка — десятичный разделитель, запятая отделяет два числа.
Цифры еще описывают дополнительные параметры команды A, которая рисует дуги.
Буквы управляют пером
Буквы — это команды, которые управляют пером. За каждой командой следуют пары координат, которые показывают, куда сместить перо или как закруглить линию. Тег path использует следующие команды:
- M — начать новую траекторию: переместить перо в заданную точку без рисования.
- Z — замкнуть траекторию: переместить перо в начальную точку и нарисовать линию.
- С, S — нарисовать кубическую кривую Безье.
- Q, T — нарисовать квадратную кривую Безье.
- L, Н и V — нарисовать произвольную, вертикальную или горизонтальную прямую.
- A — нарисовать дугу окружности или эллипса.
Команду A я пропущу, но рассмотрю остальные.
M x y
М или m начинает новую траекторию. Команда перемещает перо в заданную точку и ничего не рисует. Большое М — первая обязательная команда тега path.
<path d="M20 50..." />
Z
Z или z замыкает траекторию — проводит прямую линию от последней позиции пера к первой точке траектории. Регистр буквы не важен. Обычно это последняя команда тега. Если нет, тогда после z опять стоит большое M, которое начинает новую траекторию. Если z не написано, траектория незамкнута.
<path d="M20 50 L 10 10, 140 10, 110 50z" />
<path d="M20 50 L 10 10, 140 10, 110 50z" />
<path d="M20 50 L 10 10, 140 10z M110 50, 80 60, 95 90z" />
L x y
L или l рисует прямую линию от последней позиции пера до заданной точки. Несколько следующих друг за другом команд описывают ломаную. В такой записи, для краткости, все L, кроме первой, не пишут. Если L стоит после M, ее тоже не пишут. Вот так:
<path d="M 70,12 L 24,30 L 60,70 L 120,50" />
<path d="M 70,12 L 24,30 60,70 120,50" />
<path d="M 70,12 24,30 60,70 120,50" />
H x
H или h рисует горизонтальную линию от последней позиции пера до указанной точки. Координата у не меняется.
V x
V или v рисует вертикальную линию от последней позиции пера до указанной точки. Координата x не меняется.
C cx1 cy1 cx2 cy2 x2 y2
С или с строит кубическую кривую Безье. Она состоит из четырех точек: первая и последняя задают начало и конец кривой, две промежуточные управляют формой. Так как первая точка совпадает с текущим положением пера, то после команды C указывают только три точки: две управляющие вершины (cx1 cy1), (cx2 cy2) и последнюю точку кривой (x2 y2).
<path d="M40 50 C 60 10, 90 90, 110 50" />
Поликривая Безье — это несколько соприкасающихся кривых Безье, где конец одной кривой становится началом следующей. Последовательные команды C описывают поликривую. Для экономии байтов все команды, кроме первой C, не пишут.
<path d="M30 100C50 50,70 20,100 100,110 130,45 150,65 100" />
Обычно в месте соприкосновения кривых Безье гладкость поликривой нарушается. Чтобы поликривая оставалась гладкой, используют команду S.
S cx2 cy2 x2 y2
S или s строит гладкую кубическую кривую Безье так, что ее первая управляющая вершина является зеркальным отражением второй управляющей вершины предыдущей кривой Безье. Отражение относительно начальной точки данной кривой.
Q cx1 cy1 x2 y2
Q или q строит квадратную кривую Безье. Синтаксис команды аналогичен C, только здесь используется одна управляющая вершина.
Несколько команд Q описывают квадратную поликривую Безье. Для краткости все команды, кроме первой Q, не пишут. Чтобы квадратная поликривая получилась гладкой, используют команду T.
T x2 y2
T или t строит гладкую квадратную кривую Безье так, что ее единственная управляющая вершина является зеркальным отражением управляющей вершины предыдущей кривой Безье.
Со структурой файла разобрались.
Пишем конвертер СВГ в текст
Конвертер готов. Это экзешник. Инсталировать не нужно. Сохраните на диск и запустите.
Скачать конвертер
Для описания любого контура достаточно трех команд: M, C и Z. Конвертер понимает еще и четвертую: L, остальные — нет.
Конвертер выбирает из СВГ-файла теги path, вычисляет координаты точек траектории и сохраняет их в текстовом файле.
Конвертер не проверяет валидность СВГ-файла. Ему все равно, какая информация находится вокруг тега path. На вход конвертера можно подать любой мусор с корректными данными только в теге path.
Конвертер поддерживает пропорциональное и произвольное масштабирование координат: перед сохранением он спрашивает размер области, в которую надо вписать траекторию.
Конвертер позволяет задать позицию начала координат: в одном из углов, на середине стороны или в центре прямоугольника, ограничивающего контур.
Конвертер сохраняет в текстовом файле пары чисел — двумерные координаты точек контура. Десятичный разделитель — точка. Числа разделены пробелом.
12.3 15.6 78.4 24.1 15 123
Детали
Конвертер написан на Дельфи 7.
Пары чисел вырезаю из СВГ-файла с помощью регулярного выражения. Понимает числа разделенные пробелом, запятой или минусом.
/(-?\d+(\.\d+)?)[,|\s]?(-?\d+(\.\d+)?)\s?/
Для построения кубической кривой Безье применяю адаптивное разбиение.
Полученные данные анализирую методами геометрической морфометрии. Но это уже другая история.
С Новым годом!