{
    "version": "https:\/\/jsonfeed.org\/version\/1",
    "title": "Математик среди биологов: заметки с тегом СВГ",
    "_rss_description": "Я немного умею складывать, но от вычитания у меня всегда кружится голова",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/antonlyakh.ru\/blog\/tags\/svg\/",
    "feed_url": "https:\/\/antonlyakh.ru\/blog\/tags\/svg\/json\/",
    "icon": false,
    "author": {
        "name": "Антон Лях",
        "url": "https:\/\/antonlyakh.ru\/blog\/",
        "avatar": false
    },
    "items": [
        {
            "id": "482",
            "url": "https:\/\/antonlyakh.ru\/blog\/all\/dobavlyaem-risunki-k-listyam-dendrogrammy-ggtree\/",
            "title": "Добавляем рисунки к листьям дендрограммы в R: используем ggtree",
            "content_html": "<p class=\"loud\">Дендрограмма — это результат объединения данных при помощи иерархического кластерного анализа. Обычно на листьях дендрограммы написаны имена переменных — названия объектов. Рассказываю, как вместо названий показать изображения.<\/p>\n<p class=\"foot\">В конце заметки — <a href=\"https:\/\/antonlyakh.ru\/blog\/all\/dobavlyaem-risunki-k-listyam-dendrogrammy-ggtree\/#dend-ggtree--final-code\">финальный код на R<\/a> &darr;<\/p>\n<p><br\/><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/hc_compl__da_s0__x600.png\" width=\"500\" height=\"560\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Эта красочная дендрограмма содержит 38 листьев и разделена на 19 классов. На листьях дендрограммы написаны названия видов плоских паразитических червей из класса моногеней. Собираюсь показать вместо них изображения прикрепительных органов этих паразитов<\/div>\n<\/div>\n<p><br\/><\/p>\n<h4>Для работы понадобятся<\/h4>\n<p>Знание языка Эр.<\/p>\n<p>Установленный <a href=\"https:\/\/bioconductor.org\/packages\/release\/bioc\/html\/ggtree.html\">пакет <kbd>ggtree<\/kbd><\/a>.<\/p>\n<!-- [[https:\/\/cran.r-project.org\/web\/packages\/dendextend\/vignettes\/dendextend.html Пакет <kbd>dendextend<\/kbd>]] для построения финальных дендрограмм. --><h3>Создаю изображения объектов<\/h3>\n<p>Каждому листу дендрограммы сопоставлю маленький рисунок объекта. Для этого буду использовать два набора изображений: один — для тестирования, другой — для финальной отрисовки.<\/p>\n<p><b>Тестовые изображения<\/b><br \/>\nТестовые изображения содержат номера, идущие по порядку. Они нужны для того, чтобы было понятно, куда именно разработанный код помещает картинки.<\/p>\n<p>Вот код для генерации 99-ти пнг-файлов размером 20×20 пикселей. Имя файла с изображением совпадает с нарисованым номером.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">imgs_path = &quot;img_indexed\/&quot;\r\n\r\nfor (i in 1:99) {\r\n  # Создаю новый пнг-файл img_{i}.png с нулевыми отступами\r\n  png(file = paste0(imgs_path, &quot;img_&quot;, i, &quot;.png&quot;), width = 20, height = 20)\r\n  par(mar = c(0, 0, 0, 0))\r\n  \r\n  # Созданию рисунок числа\r\n  plot(0, 0, type = &quot;n&quot;, xlim = c(0, 1), ylim = c(0, 1), xlab = &quot;&quot;, ylab = &quot;&quot;, axes = FALSE)\r\n  text(0.5, 0.5, i, cex = 1)\r\n  \r\n  # Сохраняю пнг-файл\r\n  dev.off()\r\n}<\/code><\/pre><p>Вот сами изображения.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/numbered-images-1-99.png\" width=\"520\" height=\"130\" alt=\"\" \/>\n<\/div>\n<p>Вод код для их загрузки.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">imgs_indexed = c()\r\nimgs_path = &quot;imgs_indexed\/&quot;\r\n\r\nfor(i in 1:75) {\r\n  imgs_indexed = c(imgs_indexed, paste0(imgs_path, &quot;img_&quot;, i, &quot;.png&quot;))\r\n}<\/code><\/pre><p><b>Изображения объектов<\/b><\/p>\n<p>Изображение объекта — это уменьшенный рисунок прикрепительного крючка паразитического червя (моногенеи).  Вот они все:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/all-thumbs--ligophorus--da.png\" width=\"480\" height=\"48\" alt=\"\" \/>\n<\/div>\n<p class=\"foot\"><i>Общая картинка создана с помощью Имедж-меджик:<\/i> <kbd>montage -tile 20x2 -geometry +0+0 *.png all-anchors.png<\/kbd><\/p>\n<p>Название файла с крючком совпадает с наванием вида. Эти названия храню списком в текстовом файле <kbd>labels.txt<\/kbd>. Для загрузки изображений объектов использую следующий код.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">imgs_path = &quot;img_objects\/&quot;\r\n# Загружаем имена меток\r\nimg_objects &lt;- readLines(&quot;labels.txt&quot;)\r\n# и добавляем расширение '.png'\r\nimg_objects &lt;- paste0(imgs_path, img_objects, &quot;.png&quot;)<\/code><\/pre><p>Изображения готовы, перейдем к дереву.<\/p>\n<h3>Строю дерево с картинками, используя <kbd>ggtree<\/kbd><\/h3>\n<p>В книге «Data integration, manipulation and visualization of phylogenetic trees» описано, <a href=\"https:\/\/yulab-smu.top\/treedata-book\/chapter8.html\">как прикрутить картинки к дендрограмме с помощью <kbd>ggtree<\/kbd><\/a>.<\/p>\n<p><img src=\"https:\/\/yulab-smu.top\/treedata-book\/9781032233574_cover_review.png\" style=\"width: 200px\" \/><\/p>\n<p>К сожалению, приведнный в книге код у меня не заработал. Он подразумевает, что мы загружаем филодерево из файла. А я строю дерево при помощи иерархической кластеризации и преобразую ее в объект дендрограммы.<\/p>\n<p><kbd>data<\/kbd> — это матрица данных: <a href=\"https:\/\/antonlyakh.ru\/blog\/all\/obekt-i-priznaki-obekta-v-biologicheskoy-statistike\/#data-matrix\">в ее строках — объекты, в столбцах — признаки<\/a>.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Выполняю иерархический кластерный анализ\r\ndist &lt;- dist(data)\r\nhc   &lt;- hclust(dist, method = &quot;complete&quot;) \r\n\r\nlibrary(dendextend)\r\n\r\n# Преобразую результат в дендрограмму\r\ndend &lt;- as.dendrogram(hc)<\/code><\/pre><p>Из дендрограммы делаю филодерево.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">library(ggtree)\r\n\r\nphylo &lt;- as.phylo(dend)<\/code><\/pre><p>Рисую дерево.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ggtree(phylo)<\/code><\/pre><p>И получаю пустой каркас.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree.png\" width=\"500\" height=\"560\" alt=\"\" \/>\n<div class=\"e2-text-caption\">R: ggtree(∙)<\/div>\n<\/div>\n<h4>Строю дендрограмму с текстовыми листьями<\/h4>\n<p>Добавлю к листьям каркаса текстовые подписи при помощи функции <kbd><a href=\"https:\/\/rdrr.io\/github\/GuangchuangYu\/ggtree\/man\/geom_tiplab.html\">geom_tiplab(∙)<\/a><\/kbd>. Чтобы подписи поместились на канве, оставлю пустое место справа при помощи <kbd>xlim(∙)<\/kbd>.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ggtree(phylo) + xlim(0, 0.7) + geom_tiplab(geom=&quot;label&quot;, size=2.2)<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree-+-tiplabels.png\" width=\"500\" height=\"800\" alt=\"\" \/>\n<div class=\"e2-text-caption\">R: ggtree(∙) + xlim(∙) + geom_tiplab(label)<\/div>\n<\/div>\n<p>Получилось так себе: текст мелкий и бесит рамка вокруг него, но как от нее избавиться — не понял.<\/p>\n<p style=\"text-decoration: line-through\">Метки мелкие и иногда перекрывают друг на друга. <a href=\"https:\/\/ggrepel.slowkow.com\/articles\/examples.html\">От перекрытия меток избавит пакет <kbd>ggrepel<\/kbd><\/a>. Но в результате получается каша.<\/p>\n<h4>Рисую картинки на дендрограмме<\/h4>\n<p>У функции <kbd>geom_tiplab(∙)<\/kbd> есть параметр <kbd>geom<\/kbd>, задающий тип метки:<\/p>\n<blockquote>\n<p>one of ’text’, ’label’, ’shadowtext’, ’image’ and ’phylopic’.<\/p>\n<\/blockquote>\n<p>При помощи опции ’image’, можно на месте листьев нарисовать картинки.<\/p>\n<p>На нашей дендрограмме 38 листьев. Значит передадим ей массив из 38 тестовых изображений: <kbd>imgs_indexed[1:38]<\/kbd>.<\/p>\n<p class=\"foot\">Параметр <kbd>size<\/kbd> управляет размером картинок. Пришлось с ним повозиться, пока не подобрал подходящее значение.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ggtree(phylo) + geom_tiplab(geom=&quot;image&quot;, aes(image=imgs_indexed[1:38]), size=.03)<\/code><\/pre><p>В результате выполнения кода получил ошибку:<\/p>\n<blockquote>\n<p>Error in `label_geom()`:<br \/>\n! Problem while computing aesthetics.<br \/>\ni Error occurred in the 3rd layer.<br \/>\nCaused by error in `check_aesthetics()`:<br \/>\n! Aesthetics must be either length 1 or the same as the data (75)<br \/>\nx Fix the following mappings: `image`<\/p>\n<\/blockquote>\n<p>После длительного анализа определил, что массив изображений должен состоять из 75 элементов, что написано в сообщении об ошибке. (<nobr>75 = 38 листьев * 2 &minus; 1<\/nobr>.) Но код все равно использует только 38 первых изображений. (Это хорошо.)<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ggtree(phylo) + geom_tiplab(geom=&quot;image&quot;, aes(image=imgs_indexed[1:75]), size=.03)<\/code><\/pre><p>Вуаля.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree-+-tip-test-images.png\" width=\"500\" height=\"560\" alt=\"\" \/>\n<div class=\"e2-text-caption\">R: ggtree(∙) + xlim(∙) + geom_tiplab(image)<\/div>\n<\/div>\n<p>Подставлю сюда изображения объектов.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">ggtree(phylo) + geom_tiplab(geom=&quot;image&quot;, aes(image=img_objects[1:75]), size=.03)<\/code><\/pre><p>Цель достигнута.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree-+-tip-ligo-images-da-24x24.png\" width=\"400\" height=\"560\" alt=\"\" \/>\n<\/div>\n<p><a id=\"dend-ggtree--final-code\"><\/a><\/p>\n<h4>Финальный код<\/h4>\n<pre class=\"e2-text-code\"><code class=\"\">library(ggplot2)\r\nlibrary(ggtree)\r\n\r\n# Формируем массив с названиями файлов с рисунками объектов.\r\nimgs_path = &quot;img_objects\/&quot;\r\nimg_objects &lt;- readLines(&quot;labels.txt&quot;)\r\nimg_objects &lt;- paste0(imgs_path, img_objects, &quot;.png&quot;)\r\n\r\n# Выполняю иерархический кластерный анализ\r\ndist &lt;- dist(data)\r\nhc   &lt;- hclust(dist, method = &quot;complete&quot;) \r\n\r\n# Преобразую результат в филодерево\r\nphylo &lt;- as.phylo(dend)\r\n\r\n# Рисую дерево с картинками\r\nggtree(phylo) + geom_tiplab(geom=&quot;image&quot;, aes(image=img_objects[1:75]), size=.03)<\/code><\/pre><h3>Итог<\/h3>\n<p>Результат не нравится.<\/p>\n<p>Дендрограмма вверху заметки — красивая, а эта — средненькая. Поэтому в следующий раз покажу, как сделать красивую дендрограмму с картинками при помощи пакета <kbd>dendextend<\/kbd>.<\/p>\n<p><br\/><\/p>\n<hr \/>\n<p>Если после прочтения этой прекрасной заметки вам вдруг непреодолимо захотелось меня поблагодарить, переведите мне 200 руб. на круасан с чаем. А я пока напишу что-то новенькое.<\/p>\n<iframe src=\"https:\/\/yoomoney.ru\/quickpay\/fundraise\/button?billNumber=wfB4EAHx4LE.231103&\" width=\"330\" height=\"50\" frameborder=\"0\" allowtransparency=\"true\" scrolling=\"no\"><\/iframe>\n<p>​<\/p>\n",
            "date_published": "2023-11-26T11:31:42+03:00",
            "date_modified": "2025-05-26T22:30:35+03:00",
            "image": "https:\/\/antonlyakh.ru\/blog\/pictures\/hc_compl__da_s0__x600.png",
            "_date_published_rfc2822": "Sun, 26 Nov 2023 11:31:42 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "482",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/hc_compl__da_s0__x600.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/numbered-images-1-99.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/all-thumbs--ligophorus--da.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree-+-tiplabels.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree-+-tip-test-images.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/ggtree-+-tip-ligo-images-da-24x24.png"
                ]
            }
        },
        {
            "id": "472",
            "url": "https:\/\/antonlyakh.ru\/blog\/all\/dvoynaya-duga-v-svg-puti\/",
            "title": "Двойная дуга в СВГ пути",
            "content_html": "<p>Это короткая техническая заметка о декодировании <abbr>СВГ<\/abbr> тега <var>path<\/var>.<\/p>\n<p>Я — ретроград и у меня есть Дельфи-библиотека для загрузки СВГ графики. Она хорошо работала до тех пор, пока в теге <var>path<\/var> не встретился такой набор команд:<\/p>\n<blockquote>\n<p>... <tt>a25.35,25.35,0,0,0-.32,8.58,32.42,32.42,0,0,0,1.53,6.3<\/tt> ...<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/SVG\/Tutorial\/Paths#arcs\">По спецификации<\/a> <var>a<\/var> — рисует дугу и содержит семь параметров (семь чисел). А здесь их четырнадцать.<\/p>\n<p>Немного подумав, понял, что вторая семерка чисел определяет следующую дугу. То есть без сокращений будет так:<\/p>\n<blockquote>\n<p>... <tt>a25.35,25.35,0,0,0-.32,8.58 a32.42,32.42,0,0,0,1.53,6.3<\/tt> ...<\/p>\n<\/blockquote>\n<p>Учту это правило в библиотеке.<\/p>\n",
            "date_published": "2023-08-05T16:42:57+03:00",
            "date_modified": "2023-08-05T16:42:27+03:00",
            "_date_published_rfc2822": "Sat, 05 Aug 2023 16:42:57 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "472",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "239",
            "url": "https:\/\/antonlyakh.ru\/blog\/all\/hranim-svoi-dannye-v-svg\/",
            "title": "Храним данные в СВГ",
            "content_html": "<p>В СВГ можно хранить свои данные. Это могут быть дополнительные количественные или качественные характеристики векторной модели, которые не поддерживает формат СВГ.<\/p>\n<p>Для хранения данных придумываем новый тег <abbr><b>newtag<\/b><\/abbr>.<\/p>\n<p>СВГ основан на XML. Согласно спецификации надо описать каждый новый тег в ДТД файле, выложить его на сервер и сослаться в заголовке.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;svg ... xmlns:newtag=&quot;http:\/\/antonlyakh.ru\/new-svg-tags.dtd&quot;&gt;<\/code><\/pre><p>По факту работает, если указать пространство имен xhtml.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;svg ... xmlns:newtag=&quot;http:\/\/www.w3.org\/1999\/xhtml&quot;&gt;<\/code><\/pre><p>И работает даже если не упоминать новый тег в заголовке.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;svg ...&gt;<\/code><\/pre><p>Вставляем тег в текст.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;svg ...&gt;\r\n  &lt;newtag&gt;My own data.&lt;\/newtag&gt;\r\n&lt;\/svg&gt;<\/code><\/pre><p>Прописываем атрибуты тега.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;newtag scale=&quot;1&quot; scaleunit=&quot;mkm&quot; scalepx=&quot;254&quot; \/&gt;<\/code><\/pre><p>Комбинируем  атрибуты и содержимое.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;newtag scale=&quot;1&quot; scaleunit=&quot;mkm&quot; scalepx=&quot;254&quot;&gt;Very usefull data.&lt;\/newtag&gt;<\/code><\/pre><p>Текст на русском кодируем в УТФ-8.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;newtag lang=&quot;ru&quot;&gt;╨Я╨╛╨╝╨╜╨╕, ╤З╤В╨╛ ╤А╤Г╤Б╤Б╨║╨╕╨╣ тАФ ╨╜╨╡ ╤П╨╖╤Л╨║ ╨╝╨╡╨╢╨┤╤Г╨╜╨░╤А╨╛╨┤╨╜╨╛╨│╨╛ ╨╛╨▒╤Й╨╡╨╜╨╕╤П.&lt;\/newtag&gt;<\/code><\/pre><p>Загружаем файл в браузер — браузер правильно рисует вектор и не ругается на теги.<\/p>\n<p>Открываем файл в Иллюстраторе или Инкскейпе. Правим. Сохраняем. Смотрим исходник — теги с данными сохранились. Иллюстратор и Инскейп теги не портят.<\/p>\n<p>Мало того, можно окружить новым тегом команду рисования.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;newtag scale=&quot;1&quot; scaleunit=&quot;mkm&quot;&gt;&lt;line ... \/&gt;&lt;\/newtag&gt;<\/code><\/pre><p>Это скроет векторный объект, и он не будет виден ни в браузере, ни в векторных редакторах, но будет доступен парсеру.<\/p>\n",
            "date_published": "2018-10-18T22:26:36+03:00",
            "date_modified": "2018-10-30T23:04:45+03:00",
            "_date_published_rfc2822": "Thu, 18 Oct 2018 22:26:36 +0300",
            "_rss_guid_is_permalink": "true",
            "_rss_guid": "https:\/\/antonlyakh.ru\/blog\/all\/hranim-svoi-dannye-v-svg\/",
            "_e2_data": {
                "is_favourite": true,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "134",
            "url": "https:\/\/antonlyakh.ru\/blog\/all\/vyrezaem-pixelnuyu-grafiku-iz-vectornogo-fayla\/",
            "title": "Вырезаем растровую графику из СВГ",
            "content_html": "<p>Столкнулся с задачей.<\/p>\n<p>Есть фотография большого размера (более 4 тыс. пикселей по ширине), на которой запечатлены части живых организмов.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/big-photo-of-ligophorus-haptor.jpg\" width=\"800\" height=\"600\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Большая фотография с прикрепительными структурами плоского паразитического червя<\/div>\n<\/div>\n<p>Организмы — это паразиты. Мизерные примитивные червячки из <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%BE%D0%BD%D0%BE%D0%B3%D0%B5%D0%BD%D0%B5%D0%B8\">класса Моногеней<\/a>, живущие на жабрах рыб. К жабрам они крепятся при помощи крючков.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/ligophorus-on-liza-gills.gif\" width=\"800\" height=\"185\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Рисунок головы кефали из работы <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A1%D0%B2%D0%B5%D1%82%D0%BE%D0%B2%D0%B8%D0%B4%D0%BE%D0%B2,_%D0%90%D0%BD%D0%B0%D1%82%D0%BE%D0%BB%D0%B8%D0%B9_%D0%9D%D0%B8%D0%BA%D0%BE%D0%BB%D0%B0%D0%B5%D0%B2%D0%B8%D1%87\">Световидова<\/a> (1964); рисунок жабр и сидящего на них паразита из работы <a href=\"http:\/\/journals.plos.org\/plosone\/article?id=10.1371\/journal.pone.0142365\">Лопеса-Беленгуэра с сотоварищами (2015)<\/a><\/div>\n<\/div>\n<p>Разные виды червячков внешне очень похожи. Они отличаются только формой прикрепительных крючков. У каждого таксономического рода уникальная форма крючков, но среди видов одного рода различия форм не столь очевидны. Чтобы их обнаружить, надо использовать методы морфометрического анализа.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/diversity-of-haptoral-hooks.png\" width=\"800\" height=\"507\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Метод главных компонент описывает разнообразие форм прикрепительных крючков разных родов моногеней. График из <a href=\"http:\/\/link.springer.com\/article\/10.1007\/s11230-011-9303-1\">статьи Вигнона (2011)<\/a><\/div>\n<\/div>\n<p>Для выполнения морфометрического анализа мы оцифровываем форму крючков. Загружаем фотографию в Инскейп, обводим кривыми и сохраняем результат в СВГ.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/digitized-hooks.gif\" width=\"800\" height=\"600\" alt=\"\" \/>\n<\/div>\n<p>Проблема в том, что готовый файл слишком много «весит». Исходный джипег размером 800 Кб, после обводки и сохранения в СВГ, толстеет до 12 Мб. В результате мне присылают мегатонные свгешки с внедренной графикой, которые надо разместить на сервере, а он не резиновый.<\/p>\n<p>Я не могу выбросить фото и загрузить на сервер только векторные кривые. Потому что контуры обрисовывают несколько человек, у каждого свои особенности рисования, они ошибаются, и результаты надо перепроверять. А фотография помогает проверить правильность построения контуров.<\/p>\n<p>Я несколько часов пытался уменьшить размер свг-файла с графикой без потери качества. Попробовал уменьшить в Инскейпе, не получилось — размеры фотографии и свг-файла остались огромными. Потом разобрался с форматом и нашел решение.<\/p>\n<p>Формат СВГ поддерживает два способа хранения изображений.<\/p>\n<p>Первый, когда графический файл внедрен в СВГ. Это не оптимальный способ, потому что  файл не сжат. Изображение состоит из последовательности символов в <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Base64\">позиционной системе счисления с основанием 64<\/a> (base64). Отсюда 800 Кб превращаются в 12 Мб.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/image-embeded-in-svg.png\" width=\"800\" height=\"287\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Фотография, внедренная внутрь свг-файла, занимает очень много места<\/div>\n<\/div>\n<p>Второй, когда СВГ хранит ссылку на внешний графический файл. Тогда СВГ содержит только <a href=\"http:\/\/antonlyakh.ru\/blog\/all\/koordinaty-krivyh-iz-svg-fayla\/\">описание кривых<\/a>, а фотография хранится отдельно. Размер свг-файла становится маленьким.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/svg-jpg.png\" width=\"800\" height=\"300\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Отделил «мух» от «котлет»<\/div>\n<\/div>\n<p>Второй вариант подошел.<\/p>\n<p>Если бы файлов было мало, я бы все переконвертировал вручную. Но файлов много — несколько сотен.<\/p>\n<p>В результате написал скрипт на ПХП. Он извлекает из СВГ фотографию, сохраняет ее в виде отдельного джипега и вставляет в СВГ ссылку на этот джипег. Джипег хранится локально и называется так же, как и свг-файл.<\/p>\n<p>Скрипт умный. Если в разных файлах используется одна и та же фотография, скрипт сохранит ее всего один раз и во всех файлах будет правильно на нее ссылаться. Это экономит место.<\/p>\n<p><a href=\"https:\/\/antonlyakh.ru\/done\/extract-images-from-svg\/\"><b>Скрипт для всех<\/b><\/a>.<\/p>\n<div style=\"border: 5px solid #00ab66; padding: 6px 8px; margin-left: -14px; border-radius: 2px; margin-top: 2em\"><p>Эта заметка описывает этап создания <a href=\"http:\/\/marineparasites.org\/\">виртуальной  коллекции паразитов рыб Мирового океана<\/a><\/p>\n<\/div>",
            "date_published": "2017-02-26T11:03:37+03:00",
            "date_modified": "2021-06-10T19:08:26+03:00",
            "image": "https:\/\/antonlyakh.ru\/blog\/pictures\/big-photo-of-ligophorus-haptor.jpg",
            "_date_published_rfc2822": "Sun, 26 Feb 2017 11:03:37 +0300",
            "_rss_guid_is_permalink": "true",
            "_rss_guid": "https:\/\/antonlyakh.ru\/blog\/all\/vyrezaem-pixelnuyu-grafiku-iz-vectornogo-fayla\/",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/big-photo-of-ligophorus-haptor.jpg",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/ligophorus-on-liza-gills.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/diversity-of-haptoral-hooks.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/digitized-hooks.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/image-embeded-in-svg.png",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/svg-jpg.png"
                ]
            }
        },
        {
            "id": "135",
            "url": "https:\/\/antonlyakh.ru\/blog\/all\/svg-cleaner-utilita-kotoraya-ochischaet-svg-fayl-ot-musora\/",
            "title": "СВГ Клинер — утилита, которая очищает СВГ от мусора",
            "content_html": "<p><a href=\"https:\/\/github.com\/RazrFalcon\/SVGCleaner\">СВГ Клинер<\/a> помогает очистить СВГ-файл от мусора и без потерь уменьшить его размер.<\/p>\n<p>Без потерь значит, что утилита не разрушает СВГ. Она сохраняет векторные объекты и:<\/p>\n<ul>\n<li>удаляет данные, которые внедряют в файл векторные редакторы, не нужные для отображения свг-файла;<\/li>\n<li>оптимизирует структуру СВГ;<\/li>\n<li>удаляет невидимые или неиспользуемые элементы.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/RazrFalcon\/SVGCleaner\"><b>Проект на Гитхабе<\/b><\/a>. Есть <a href=\"https:\/\/github.com\/RazrFalcon\/svgcleaner-gui\/releases\">версия с графическим интерфейсом<\/a>.<\/p>\n",
            "date_published": "2017-02-25T14:35:19+03:00",
            "date_modified": "2017-04-29T16:46:32+03:00",
            "_date_published_rfc2822": "Sat, 25 Feb 2017 14:35:19 +0300",
            "_rss_guid_is_permalink": "true",
            "_rss_guid": "https:\/\/antonlyakh.ru\/blog\/all\/svg-cleaner-utilita-kotoraya-ochischaet-svg-fayl-ot-musora\/",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "12",
            "url": "https:\/\/antonlyakh.ru\/blog\/all\/koordinaty-krivyh-iz-svg-fayla\/",
            "title": "Координаты кривых из СВГ файла",
            "content_html": "<p><span style=\"display: inline-block; font-weight: bold; padding: 6px; background-color: #7fC\"><a href=\"http:\/\/antonlyakh.ru\/download\/?svg2txt\">Скачать конвертер<\/a><\/span><\/p>\n<p>Для работы мне необходимы контуры микроорганизмов, которые я использую для сравнения форм. Я получаю контуры из фотографий, очерчивая объект в векторном редакторе. Программа сохраняет результат в СВГ файле, а мне нужны живые координаты точек. Чтобы получить координаты, я анализирую СВГ файл.<\/p>\n<p>СВГ файл состоит из тегов. Я разберу только один — <abbr>path<\/abbr>, — остальные мне не нужны. Он хранит описание криволинейных и замкнутых траекторий. Траектория — это и есть тот самый контур микроорганизма.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/trajectory.jpg\" width=\"600\" height=\"505\" alt=\"\" \/>\n<\/div>\n<h2>Учим синтаксис тега <abbr>path<\/abbr><\/h2>\n<p>Описание траектории вложено в тег <abbr>svg<\/abbr>. Примерно так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Заголовок подтверждающий, что это СВГ\r\n&lt;svg&gt;\r\n  &lt;path ... \/&gt;\r\n&lt;\/svg&gt;<\/code><\/pre><p>Тег <abbr>path<\/abbr> содержит один атрибут <abbr>d<\/abbr> с алгоритмом рисования траектории.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;алгоритм рисования&quot; \/&gt;<\/code><\/pre><p>Алгоритм состоит из <i>букв-команд<\/i> и <i>цифр-координат,<\/i> которые разделенны <i>пробелом, запятой<\/i> или <i>знаком минус.<\/i> Траекторию рисует перо, буквы-команды управляют, цифры-координаты показывают куда или как сместить перо, а разделители отделяют одно от другого.<\/p>\n<h3>Разделители разделяют<\/h3>\n<p>Пробел — это стандартный разделитель. Его можно ставить везде между командами и координатами. Спецификация СВГ разрешает не писать пробел, когда из контекста понятно, что здесь две разные сущности. Это сокращает объем СВГ-файла.<\/p>\n<p>Запомним:<\/p>\n<ul>\n<li>пробел не нужен между командой и числом;<\/li>\n<li>пробел не нужен после запятой;<\/li>\n<li>пробел не нужен перед знаком минус.<\/li>\n<\/ul>\n<p>Запятая тоже разделяет два числа, но вместо нее можно написать пробел. Что именно написать — дело вкуса.<\/p>\n<p>Следующие три записи эквивалентны, но последняя компактнее.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M 15 17 L 18 -23 Z&quot; \/&gt;\r\n&lt;path d=&quot;M 15, 17 L 18, -23 Z&quot; \/&gt;\r\n&lt;path d=&quot;M15,17L18-23Z&quot; \/&gt;<\/code><\/pre><p>Теперь о цифрах.<\/p>\n<h3>Цифры хранят координаты<\/h3>\n<p>СВГ предназначен для хранения двумерной графики. Поэтому цифры задают координаты точек на плоскости. Для каждой точки используется два числа — первое для <i>x<\/i>, второе для <i>y<\/i>.<\/p>\n<p>Координаты бывают абсолютными и относительными. Абсолютные координаты отсчитываются от нуля, относительные — от конечной точки предыдущей команды. Относительные — это шаг, на который надо сдвинуть перо относительно последней позиции.<\/p>\n<p>Тип координат определяет регистр буквы-команды: большая буква обозначает абсолютную позицию, маленькая — относительную.<\/p>\n<blockquote>\n<blockquote>\n<p>Заглавная буква-команда — для абсолютных координат, прописная — для относительных<\/p>\n<\/blockquote>\n<\/blockquote>\n<p>Точка является десятичным разделителем вещественных чисел. Запись <abbr>12,75<\/abbr> — это два числа: 12 и 75, тогда как <abbr>12.75<\/abbr> — это одно вещественное число.<\/p>\n<blockquote>\n<blockquote>\n<p>Точка — десятичный разделитель, запятая отделяет два числа.<\/p>\n<\/blockquote>\n<\/blockquote>\n<p>Цифры еще описывают дополнительные параметры команды <b>A<\/b>, которая рисует дуги.<\/p>\n<h3>Буквы управляют пером<\/h3>\n<p>Буквы — это команды, которые управляют пером. За каждой командой следуют пары координат, которые показывают, куда сместить перо или как закруглить линию. Тег <abbr>path<\/abbr> использует следующие команды:<\/p>\n<ul>\n<li><b>M<\/b> — начать новую траекторию: переместить перо в заданную точку без рисования.<\/li>\n<li><b>Z<\/b> — замкнуть траекторию: переместить перо в начальную точку и нарисовать линию.<\/li>\n<li><b>С<\/b>, <b>S<\/b> — нарисовать кубическую кривую Безье.<\/li>\n<li><b>Q<\/b>, <b>T<\/b> — нарисовать квадратную кривую Безье.<\/li>\n<li><b>L<\/b>, <b>Н<\/b> и <b>V<\/b> — нарисовать произвольную, вертикальную или горизонтальную прямую.<\/li>\n<li><b>A<\/b> — нарисовать дугу окружности или эллипса.<\/li>\n<\/ul>\n<p>Команду <b>A<\/b> я пропущу, но рассмотрю остальные.<\/p>\n<h5><i>M x y<\/i><\/h5>\n<p><b>М<\/b> или <b>m<\/b> начинает новую траекторию. Команда перемещает перо в заданную точку и ничего не рисует. Большое <b>М<\/b> — первая обязательная команда тега <abbr>path<\/abbr>.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M20 50...&quot; \/&gt;<\/code><\/pre><h5><i><b>Z<\/b><\/i><\/h5>\n<p><b>Z<\/b> или <b>z<\/b> замыкает траекторию — проводит прямую линию от последней позиции пера к первой точке траектории. Регистр буквы не важен. Обычно это последняя команда тега. Если нет, тогда после <b>z<\/b> опять стоит большое <b>M<\/b>, которое начинает новую траекторию. Если <b>z<\/b> не написано, траектория незамкнута.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M20 50 L 10 10, 140 10, 110 50z&quot; \/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/open-path.gif\" width=\"384\" height=\"132\" alt=\"\" \/>\n<\/div>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M20 50 L 10 10, 140 10, 110 50z&quot; \/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/closed-path.gif\" width=\"374\" height=\"132\" alt=\"\" \/>\n<\/div>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M20 50 L 10 10, 140 10z M110 50, 80 60, 95 90z&quot; \/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/two-closed-path.gif\" width=\"374\" height=\"234\" alt=\"\" \/>\n<\/div>\n<h5><i><b>L<\/b> x y<\/i><\/h5>\n<p><b>L<\/b> или <b>l<\/b> рисует прямую линию от последней позиции пера до заданной точки. Несколько следующих друг за другом команд описывают ломаную. В такой записи, для краткости, все <b>L<\/b>, кроме первой, не пишут. Если <b>L<\/b> стоит после <b>M<\/b>, ее тоже не пишут. Вот так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M 70,12 L 24,30 L 60,70 L 120,50&quot; \/&gt;\r\n&lt;path d=&quot;M 70,12 L 24,30 60,70 120,50&quot; \/&gt;\r\n&lt;path d=&quot;M 70,12 24,30 60,70 120,50&quot; \/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/polyline.gif\" width=\"266\" height=\"172\" alt=\"\" \/>\n<\/div>\n<h5><i><b>H<\/b> x<\/i><\/h5>\n<p><b>H<\/b> или <b>h<\/b> рисует горизонтальную линию от последней позиции пера до указанной точки. Координата <i>у<\/i> не меняется.<\/p>\n<h5><i><b>V<\/b> x<\/i><\/h5>\n<p><b>V<\/b> или <b>v<\/b> рисует вертикальную линию от последней позиции пера до указанной точки. Координата <i>x<\/i> не меняется.<\/p>\n<h5><i><b>C<\/b> cx<sub>1<\/sub> cy<sub>1<\/sub> cx<sub>2<\/sub> cy<sub>2<\/sub> x<sub>2<\/sub> y<sub>2<\/sub><\/i><\/h5>\n<p><b>С<\/b> или <b>с<\/b> строит кубическую кривую Безье. Она состоит из четырех точек: первая и последняя задают начало и конец кривой, две промежуточные управляют формой. Так как первая точка совпадает с текущим положением пера, то после команды <b>C<\/b> указывают только три точки: две управляющие вершины (<i>cx<sub>1<\/sub> cy<sub>1<\/sub><\/i>), (<i>cx<sub>2<\/sub> cy<sub>2<\/sub><\/i>) и последнюю точку кривой (<i>x<sub>2<\/sub> y<sub>2<\/sub><\/i>).<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M40 50 C 60 10, 90 90, 110 50&quot; \/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/bezier.gif\" width=\"314\" height=\"118\" alt=\"\" \/>\n<\/div>\n<p><i>Поликривая Безье<\/i> — это несколько соприкасающихся кривых Безье, где конец одной кривой становится началом следующей. Последовательные команды <b>C<\/b> описывают поликривую. Для экономии байтов все команды, кроме первой <b>C<\/b>, не пишут.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;path d=&quot;M30 100C50 50,70 20,100 100,110 130,45 150,65 100&quot; \/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/bezier-polyline.gif\" width=\"270\" height=\"302\" alt=\"\" \/>\n<\/div>\n<p>Обычно в месте соприкосновения кривых Безье гладкость поликривой нарушается. Чтобы поликривая оставалась гладкой, используют команду <b>S<\/b>.<\/p>\n<h5><i><b>S<\/b> cx<sub>2<\/sub> cy<sub>2<\/sub> x<sub>2<\/sub> y<sub>2<\/sub><\/i><\/h5>\n<p><b>S<\/b> или <b>s<\/b> строит гладкую кубическую кривую Безье так, что ее первая управляющая вершина является зеркальным отражением второй управляющей вершины предыдущей кривой Безье. Отражение относительно начальной точки данной кривой.<\/p>\n<h5><i><b>Q<\/b> cx<sub>1<\/sub> cy<sub>1<\/sub> x<sub>2<\/sub> y<sub>2<\/sub><\/i><\/h5>\n<p><b>Q<\/b> или <b>q<\/b> строит квадратную кривую Безье. Синтаксис команды аналогичен <b>C<\/b>, только здесь используется одна управляющая вершина.<\/p>\n<p>Несколько команд <b>Q<\/b> описывают квадратную поликривую Безье. Для краткости все команды, кроме первой <b>Q<\/b>, не пишут. Чтобы квадратная поликривая получилась гладкой, используют команду <b>T<\/b>.<\/p>\n<h5><i><b>T<\/b> x<sub>2<\/sub> y<sub>2<\/sub><\/i><\/h5>\n<p><b>T<\/b> или <b>t<\/b> строит гладкую квадратную кривую Безье так, что ее единственная управляющая вершина является зеркальным отражением управляющей вершины предыдущей кривой Безье.<\/p>\n<p>Со структурой файла разобрались.<\/p>\n<p><a name=\"svg-converter\"><\/a><\/p>\n<h3>Пишем конвертер СВГ в текст<\/h3>\n<p>Конвертер готов. Это экзешник. Инсталировать не нужно. Сохраните на диск и запустите.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/antonlyakh.ru\/blog\/pictures\/svg-converter.gif\" width=\"645\" height=\"446\" alt=\"\" \/>\n<\/div>\n<p><span style=\"display: inline-block; font-weight: bold; padding: 6px; background-color: #7fC\"><a href=\"http:\/\/antonlyakh.ru\/download\/?svg2txt\">Скачать конвертер<\/a><\/span><\/p>\n<p>Для описания любого контура достаточно трех команд: <abbr>M<\/abbr>, <abbr>C<\/abbr> и <abbr>Z<\/abbr>. Конвертер понимает еще и четвертую: <abbr>L<\/abbr>, остальные — нет.<\/p>\n<p>Конвертер выбирает из СВГ-файла теги <abbr>path<\/abbr>, вычисляет координаты точек траектории и сохраняет их в текстовом файле.<\/p>\n<p>Конвертер не проверяет валидность СВГ-файла. Ему все равно, какая информация находится вокруг тега <abbr>path<\/abbr>. На вход конвертера можно подать любой мусор с корректными данными только в теге <abbr>path<\/abbr>.<\/p>\n<p>Конвертер поддерживает пропорциональное и произвольное масштабирование координат: перед сохранением он спрашивает размер области, в которую надо вписать траекторию.<\/p>\n<p>Конвертер позволяет задать позицию начала координат: в одном из углов, на середине стороны или в центре прямоугольника, ограничивающего контур.<\/p>\n<p>Конвертер сохраняет в текстовом файле пары чисел — двумерные координаты точек контура. Десятичный разделитель — точка. Числа разделены пробелом.<\/p>\n<p><abbr>12.3 15.6 78.4 24.1 15 123<\/abbr><\/p>\n<h3>Детали<\/h3>\n<p>Конвертер написан на Дельфи 7.<\/p>\n<p>Пары чисел вырезаю из СВГ-файла с помощью регулярного выражения. Понимает числа разделенные пробелом, запятой или минусом.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/(-?\\d+(\\.\\d+)?)[,|\\s]?(-?\\d+(\\.\\d+)?)\\s?\/<\/code><\/pre><p>Для построения кубической кривой Безье применяю <a href=\"https:\/\/rsdn.ru\/article\/multimedia\/Bezier.xml\">адаптивное разбиение<\/a>.<\/p>\n<p>Полученные данные анализирую методами геометрической морфометрии. Но это уже другая история.<\/p>\n<p>С Новым годом!<\/p>\n",
            "date_published": "2015-12-30T19:29:28+03:00",
            "date_modified": "2016-03-14T19:42:28+03:00",
            "image": "https:\/\/antonlyakh.ru\/blog\/pictures\/trajectory.jpg",
            "_date_published_rfc2822": "Wed, 30 Dec 2015 19:29:28 +0300",
            "_rss_guid_is_permalink": "true",
            "_rss_guid": "https:\/\/antonlyakh.ru\/blog\/all\/koordinaty-krivyh-iz-svg-fayla\/",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/trajectory.jpg",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/open-path.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/closed-path.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/two-closed-path.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/polyline.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/bezier.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/bezier-polyline.gif",
                    "https:\/\/antonlyakh.ru\/blog\/pictures\/svg-converter.gif"
                ]
            }
        }
    ],
    "_e2_version": 3559,
    "_e2_ua_string": "E2 (v3559; Aegea)"
}