Как установить размер вывода в GraphViz для точечного формата?
Я хочу убедиться, что все узлы находятся в некотором диапазоне (скажем, [0,0,W,H]) после размещения.
Я полагал, что ограничивающая рамка будет решением с помощью bb
атрибут, но и точка, и neato просто перезаписывают его.
Например мой график:
strict digraph {
1,2,3;
1 -> 3;
3 -> 2;
}
Выход из neato -Gbb="0,0,50,50" -T dot file.txt
:
strict digraph {
graph [bb="0,0,120.49,162.36"];
node [label="\N"];
1 [height=0.5,
pos="27,18",
width=0.75];
3 [height=0.5,
pos="70.233,75.918",
width=0.75];
1 -> 3 [pos="e,57.954,59.469 39.043,34.133 43.004,39.441 47.504,45.468 51.827,51.261"];
2 [height=0.5,
pos="93.485,144.36",
width=0.75];
3 -> 2 [pos="e,87.436,126.56 76.221,93.545 78.643,100.67 81.496,109.07 84.177,116.97"];
}
Я получаю одинаковые позиции для любого значения bb
или любая комбинация size
а также dpi
,
Что мне нужно, так это чтобы все узлы находились внутри данного блока.
Любые предложения, как это сделать?
Полный рассказ:
Я использую *graphviz_layout* из networkx для разметки моего графика. Я рисую график с помощью пирообработки. Я хочу избежать повторного масштабирования результатов из *graphviz_layout*, если вместо этого есть способ сообщить мои границы.
1 ответ
Вот версия TL;DR:
Чтобы создать PNG-изображение размером 900 на 1500 пикселей из графика в foo.gv, вы можете запустить:
dot -Tpng -Gsize=9,15\! -Gdpi=100 -ofoo.png foo.gv
получить изображение шириной ровно 900 пикселей или высотой 1500, но не обязательно оба; а потом:
convert foo.png -gravity center -background white -extent 900x1500 final.png
заполнить изображение пробелами так, чтобы оно было точно 900 на 1500 пикселей; где convert
является частью пакета ImageMagick.
Вот подробное объяснение:
Чтобы уточнить:
bb
атрибут помечен как "только для записи", поэтому ни один из механизмов компоновки Graphviz, скорее всего, не будет учитывать любые значения, которые вы передаете перед обработкой.В общем случае Graphviz может генерировать как векторную (масштабируемую), так и растровую графику, поэтому DPI не всегда является значимым показателем.
В частности,
dpi
Атрибут действителен только для растровых и SVG форматов вывода.
То, что вы пытаетесь сделать, немного сложнее, так как размер пикселя изображения, сгенерированного Graphviz, определяется парой взаимодействующих атрибутов.
Давайте возьмем произвольный граф в качестве примера.
Команда gvgen -dh3
будет генерировать направленный гиперкуб степени три. (Если вам нужна более подробная информация об этом, PDF-версия справочной страницы gvgen находится здесь, но это не имеет значения, это просто произвольный график для демонстрационных целей.)
Сгенерированная по умолчанию точка PNG-рендеринга этого графика может быть создана с помощью команды:
gvgen -dh3 | dot -Tpng -oexample.png
Когда я это делаю, я получаю изображение PNG-формата (растровое изображение) 275 x 347 пикселей. (Как сообщает file example.png
.)
size
Атрибут позволяет рекомендовать максимальную или желаемую высоту и ширину для выходного изображения в дюймах. Т.е. атрибут size=3,5
говорит Графику, что нужно создать изображение размером не более 3 на 5 дюймов. Если изображение меньше чем 3 на 5 для начала, Graphviz оставит его в покое. Если для начала размер изображения превышает 3 на 5 дюймов, Graphviz будет уменьшать его до тех пор, пока он не уместится на холсте размером 3 на 5 дюймов (с сохранением соотношения сторон исходного изображения).
Добавление восклицательного знака изменяет size
атрибут от максимального размера до желаемого размера. Теперь, если оба размера меньше указанного размера, чертеж масштабируется до тех пор, пока хотя бы одно измерение не будет равно указанному размеру.
Например, работает:
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -oexample.png
(Обратите внимание, что \!
ускользает от восклицательного знака для Баш. В файле DOT вы просто напишите size=3,5!
.)
генерирует изображение размером 288 x 363 пикселя, немного больше в обоих измерениях, чем по умолчанию.
Как точка пришла с этими числами? Ну, значение DPI по умолчанию для Graphviz составляет 96 пикселей на дюйм. При таком разрешении изображение размером 3 на 5 дюймов представляет собой изображение размером 288 на 480 пикселей. Механизм макета просто увеличил изображение до тех пор, пока хотя бы одно из размеров не соответствовало желаемому размеру.
Вы можете переопределить значение DPI по умолчанию, используя dpi
атрибут, вот так:
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=200 -oexample.png
Теперь сгенерированное изображение имеет размеры 600 на 757 пикселей. Опять же, Graphviz просто масштабировал изображение до тех пор, пока одно из измерений не совпало с желаемым размером (но при этом разрешении изображение размером 3 на 5 дюймов - это изображение размером 600 на 1000 пикселей).
Следовательно, если вы хотите создать изображение, которое содержит произвольное количество пикселей, вам нужно установить оба size
а также dpi
соответственно.
Т.е. предположим, что вы хотите создать изображение размером 900 на 1500 пикселей. Вы можете использовать:
gvgen -dh3 | dot -Tpng -Gsize=9,15\! -Gdpi=100 -oexample.png
или же
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=300 -oexample.png
или даже:
gvgen -dh3 | dot -Tpng -Gsize=900,1500\! -Gdpi=1 -oexample.png
(Но в то время как этот последний показался мне быстрым, я бы рекомендовал придерживаться более обычного значения DPI на всякий случай.)
Это решает большую часть вашей проблемы, но обратите внимание, что Graphviz масштабирует изображение только до тех пор, пока одно из измерений не будет соответствовать указанному размеру. В зависимости от соотношения сторон вашего исходного изображения вы можете получить или не получить точный размер, который вы ищете.
Это где ratio
атрибут вступает в игру.
Команда:
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=300 -Gratio=fill -oexample.png
должен дать вам изображение с точным размером, который вы ищете, но с несколькими оговорками:
На практике иногда кажется, что размер немного отличается от желаемого. Например, когда я запускаю указанную выше команду, я получаю изображение размером 900 на 1472 пикселя (а не 900 на 1500). Я не знаю, связано ли это с ошибкой округления или с чем.
Для этого Graphviz должен масштабировать макет независимо в каждом измерении. Он достаточно умен, чтобы масштабировать макет, а не изображение, поэтому изображение само по себе не искажается, но в зависимости от того, насколько запрошенное соотношение сторон отличается от "естественного" соотношения макета, горизонтальное и вертикальное расстояние может выглядеть немного странно.
ratio
также принимает несколько разных значений. Посмотрите документацию и / или немного поэкспериментируйте, чтобы увидеть, что они делают.
Для чего стоит, если вы буквально хотите получить изображение с точными размерами в пикселях, которые вы запрашиваете, я бы предложил, чтобы Graphviz масштабировал изображение так, чтобы совпадало одно из двух измерений, а затем использовал что-то вроде ImageMagick, чтобы дополнить изображение до получите точное соотношение сторон, которое вы ищете. Например, команда:
convert in.png -gravity center -background white -extent 900x1500 out.png
будет центрировать изображение (от in.png
) на холсте 900 на 1500 пикселей (сохраняя его в out.png
) путем заполнения горизонтального или вертикального размера по мере необходимости