Пакет для рисования RDF-графиков

Пакет для рисования RDF-графиков

Есть ли какой-нибудь пакет для рисования хороших RDF-графиков, например, как показано ниже (взято изтам)?

Можно ли создать такой график (в том же стиле) в TikZ?

введите описание изображения здесь

решение1

В первую очередь я бы начал с определения стиля, способного представлять вершины; в основном нам нужно:

  1. эллипс;
  2. некоторые определения размеров;
  3. сделать границу толще и установить цвет заливки ярче по отношению к границе;
  4. сделать текст белым;
  5. возможно, стоит немного уменьшить размер шрифта текста.

Определение стиля в TikZ можно выполнить с помощью \tikzset:

\tikzset{vertex style/.style={
    draw=#1,
    thick,
    fill=#1!70,
    text=white,
    ellipse,
    minimum width=2cm,
    minimum height=0.75cm,
    font=\small,
    outer sep=3pt, % the usage of this option will be clear later on
  },
}

Обратите внимание на две вещи: этот стиль получает аргумент, цвет, и устанавливает цвет заливки ярче, смешивая цвет с белым. Во-вторых, фигура ellipseтребует библиотеку:

\usetikzlibrary{shapes.geometric}

Давайте теперь создадим первую вершину. Я бы начал с "Righteous Kill", от которой отходит больше всего связей.

\documentclass[dvipsnames,png,border=10pt,tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric} % required for the ellipse shape
\tikzset{vertex style/.style={
    draw=#1,
    thick,
    fill=#1!70,
    text=white,
    ellipse,
    minimum width=2cm,
    minimum height=0.75cm,
    font=\small,
    outer sep=3pt,
  },
}
\begin{document}
\begin{tikzpicture}
\node[vertex style=Turquoise] (Rk) {Righteous Kill};
\end{tikzpicture}
\end{document}

Будьте осторожны с этой опцией dvipsnames: ее необходимо было установить в параметрах класса, чтобы предотвратить возможную option clashошибку, поскольку TikZ загружает сам себя xcolor.

Узел использует определенный выше стиль, устанавливая свой цвет (определение в xcolorруководстве), свое имя (Rk)и свой текст {Righteous Kill}.

Результат:

введите описание изображения здесь

С этого момента я не буду показывать преамбулу, а только код изображения.

Вторым шагом является определение местоположения других узлов. Можно использовать множество возможностей (используя GraphViz, используя объектно-ориентированный модуль PGF и создавая некоторый пользовательский класс - см.:Построение связей между элементами базы данных): здесь я использую positioningбиблиотеку TikZ. Каждая вершина, таким образом, будет располагаться, начиная с положения других вершин, ссылаясь на их имена.

Примечание: поскольку каждая вершина должна быть соединена с другой, синтаксис

\node[options] (a) {text a} ... edge[options] node[options]{text conn} (b);

соединит вершины aи bустановит метку для соединения text conn. Крайне полезно в этом случае. Действительно, давайте начнем добавлять еще один узел:

\begin{tikzpicture}[node distance=2.75cm,>=stealth']
\node[vertex style=Turquoise] (Rk) {Righteous Kill};

\node[vertex style=BurntOrange, above of=Rk,xshift=2em] (BD) {Bryan Dennehy}
 edge [<-,cyan!60!blue] node[text style,above]{starring} (Rk);
\end{tikzpicture}

Параметры node distance=2.75cm,>=stealth'касаются базового расстояния вершин и типа наконечника стрелки, используемого для соединения. В зависимости от выбранного наконечника стрелки arrowsдолжна быть загружена библиотека.

Обратите внимание, что текст соединения требует стиля: text style. Его определение:

\tikzset{
  text style/.style={
    sloped, % the text will be parallel to the connection 
    text=black,
    font=\footnotesize,
    above
  }
}

Местоположение нового узла задается с помощью опций above of=Rk,xshift=2em: первая задает позицию относительно имени предыдущего узла, который мы создали ранее, вторая немного сдвигает эту позицию вправо.

Результат:

введите описание изображения здесь

Поняв этот механизм, можно найти все остальные узлы:

\begin{tikzpicture}[node distance=2.75cm,>=stealth']
\node[vertex style=Turquoise] (Rk) {Righteous Kill};

\node[vertex style=BurntOrange, above of=Rk,xshift=2em] (BD) {Bryan Dennehy}
 edge [<-,cyan!60!blue] node[text style]{starring} (Rk);

\node[vertex style=BurntOrange, right=1.5cm of Rk,yshift=4ex] (AP) {Al Pacino}
 edge [<-,cyan!60!blue] node[text style]{starring} (Rk); 

\node[vertex style=red, below right of=Rk,xshift=2em] (JA) {John Avnet}
 edge [<-,cyan!60!blue] node[text style]{director} (Rk); 

 \node[vertex style=BurntOrange, right=1.5cm of Rk,yshift=-4ex] (RN) {Robert De Niro}
 edge [<-,cyan!60!blue] node[text style]{starring} (Rk); 

\node[vertex style=MidnightBlue, above right of=Rk,xshift=2em] (Dr) {Drama}
 edge [<-,cyan!60!blue] node[text style]{genre} (Rk); 

\node[vertex style=Maroon, below of=Rk,xshift=-2em] (Skf) {Serial Killer Films}
 edge [<-,cyan!60!blue] node[text style]{subject} (Rk);

\node[vertex style=Maroon, below right of=Skf] (Cf) {Crime Films}
 edge [<-,cyan!60!blue] node[text style]{broader} (Skf);
\end{tikzpicture}

введите описание изображения здесь

После того, как эта задача выполнена, можно приступить к добавлению «жидкого» фона вокруг некоторых вершин.

Чтобы разместить что-то на заднем плане, библиотека backgroundsпоможет, а также библиотека Эндрю Стейси для рисования плавной кривой. Более того, часто требуются некоторые вычисления, поэтому также следует загрузить hobbyбиблиотеку .calc

Определение пути должно быть сделано следующим образом: начиная с севера узла (Rk), обходят все возможные якоря интересующих узлов, которые должны быть выделены. Существуют некоторые автоматические инструменты, см.Реализация хобби-пути в подходе выпуклой оболочки, но они не могут быть точными и тонкими, как некоторые ручные работы. И, в данном случае, это позволяет достичь наилучшего результата.

\begin{pgfonlayer}{background}
\draw[Maroon,fill=Maroon,dashed,fill opacity=0.1](Rk.north) 
to[closed,curve through={(Rk.north west).. (Rk.west) .. (Rk.south west) 
..($(Rk.south west)!0.5!(Skf.north)$) .. (Skf.north     west).. (Skf.west) 
.. (Skf.south west) .. ($(Skf.south)!0.75!(Cf.west)$) .. (Cf.west) 
.. (Cf.south west) .. (Cf.south) .. (Cf.south east) .. (Cf.east) 
.. ($(Cf.north east)!0.65!(Skf.south east)$) .. (Skf.east) 
.. (Skf.north east).. ($(Skf.north)!0.35!(Rk.south east)$) 
.. (Rk.south east) .. (Rk.east)..(Rk.north east)}](Rk.north);
\end{pgfonlayer}

Примерно таков код... но вот результат:

введите описание изображения здесь

Таинственная опция outer sep=3ptпозволяет не располагать "жидкий фон" слишком близко к границе формы. И вот все!

Полный код для справки:

\documentclass[dvipsnames,png,border=10pt,tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric} % required for the ellipse shape
\usetikzlibrary{arrows, backgrounds, calc, hobby, positioning}

% this avoides some problem with the hobby implementation
% egreg's code from:
% http://www.guitex.org/home/it/forum/5-tex-e-latex/83195-la-libreria-hobby-tikz-non-funziona-piu#83203
\ExplSyntaxOn
\cs_if_exist:NF \prg_stepwise_function:nnnN { \cs_gset_eq:NN \prg_stepwise_function:nnnN \int_step_function:nnnN }
\cs_if_exist:NF \prg_stepwise_inline:nnnn { \cs_gset_eq:NN \prg_stepwise_inline:nnnn \int_step_inline:nnnn }
\ExplSyntaxOff

\tikzset{vertex style/.style={
    draw=#1,
    thick,
    fill=#1!70,
    text=white,
    ellipse,
    minimum width=2cm,
    minimum height=0.75cm,
    font=\small,
    outer sep=3pt,
  },
  text style/.style={
    sloped,
    text=black,
    font=\footnotesize,
    above
  }
}

\begin{document}
\begin{tikzpicture}[node distance=2.75cm,>=stealth']
\node[vertex style=Turquoise] (Rk) {Righteous Kill};

\node[vertex style=BurntOrange, above of=Rk,xshift=2em] (BD) {Bryan Dennehy}
 edge [<-,cyan!60!blue] node[text style]{starring} (Rk);

\node[vertex style=BurntOrange, right=1.5cm of Rk,yshift=4ex] (AP) {Al Pacino}
 edge [<-,cyan!60!blue] node[text style]{starring} (Rk); 

\node[vertex style=red, below right of=Rk,xshift=2em] (JA) {John Avnet}
 edge [<-,cyan!60!blue] node[text style]{director} (Rk); 

 \node[vertex style=BurntOrange, right=1.5cm of Rk,yshift=-4ex] (RN) {Robert De Niro}
 edge [<-,cyan!60!blue] node[text style]{starring} (Rk); 

\node[vertex style=MidnightBlue, above right of=Rk,xshift=2em] (Dr) {Drama}
 edge [<-,cyan!60!blue] node[text style]{genre} (Rk); 

\node[vertex style=Maroon, below of=Rk,xshift=-2em] (Skf) {Serial Killer Films}
 edge [<-,cyan!60!blue] node[text style]{subject} (Rk);

\node[vertex style=Maroon, below right of=Skf] (Cf) {Crime Films}
 edge [<-,cyan!60!blue] node[text style]{broader} (Skf);

\begin{pgfonlayer}{background}
\draw[Maroon,fill=Maroon,dashed,fill opacity=0.1](Rk.north) 
to[closed,curve through={(Rk.north west).. (Rk.west) .. (Rk.south west) 
..($(Rk.south west)!0.5!(Skf.north)$) .. (Skf.north     west).. (Skf.west) 
.. (Skf.south west) .. ($(Skf.south)!0.75!(Cf.west)$) .. (Cf.west) 
.. (Cf.south west) .. (Cf.south) .. (Cf.south east) .. (Cf.east) 
.. ($(Cf.north east)!0.65!(Skf.south east)$) .. (Skf.east) 
.. (Skf.north east).. ($(Skf.north)!0.35!(Rk.south east)$) 
.. (Rk.south east) .. (Rk.east)..(Rk.north east)}](Rk.north);
\end{pgfonlayer}

\end{tikzpicture}
\end{document}

Связанный контент