FAQ
ここで質問への回答が見つからない場合は、Graphvizフォーラムで質問してください。
- 貢献
- FaqPSdefs ISO-latin1フォントのPostScript定義(Enrique Vidal氏による)
一般
dotまたはneatoを制御するすべての属性のリストはどこで見ることができますか?
グラフ属性を参照してください。 コマンドラインの使用法と出力形式に関する情報もあります。
Graphvizについて議論できる場所はどこですか?
質問やコメントはGraphvizフォーラムに投稿してください。
レイアウトを大きくしようとしています。どのようにすればよいですか?
レイアウトのサイズを増やす方法はいくつかあります。これを行う際には、ノードとテキストのサイズも増やすかどうかを決定する必要があります。
1つの方法は、fontsize、nodesep、ranksepなどの個々のパラメーターを調整することです。たとえば、
digraph G {
graph [fontsize=24]
edge [fontsize=24]
node [fontsize=24]
ranksep = 1.5
nodesep = .25
edge [style="setlinewidth(3)"]
a -> b -> c
}
これを行う場合は、size="6,6"
など、競合するグラフサイズ設定と競合していないことを確認してください。そうしないと、すべてが縮小されます。
fdpまたはneatoを使用している場合、エッジlenを増やすとレイアウトが拡大する傾向があります。
graph G {
layout="neato"
edge [len=3]
a -- { b c d }
}
twopiとcircoの場合、ranksep
など、使用できる他のパラメーターがあります。グラフ属性を参照してください。
ratio
属性を使用することもできます。size
属性を目的の描画サイズに設定し、ratio=fill
を設定すると、ノードの位置はxとyで個別に拡大縮小され、描画が指定されたサイズを満たすようになります。ノードのサイズは変わりません。代わりにratio=expand
を設定すると、レイアウトはxとyで均一に拡大縮小され、少なくとも1つの次元がサイズに適合するようになります。
size
属性を指定し、最後に感嘆符(!)を付ける場合、最終的な図面は、少なくとも一方の次元が size に適合するまで、x と y の両方で均一に拡大されます。テキストやノードのサイズも含め、すべてが拡大されることに注意してください。
PostScript を使用している場合は、2 2 scale
のようなコマンドを手動で追加して出力を拡大できます(PostScript 環境が設定されている場合)。ツールがこのヘッダーを参照する場合は、BoundingBox も調整してください。
dotで特定のエッジルートを結合またはマージするにはどうすればよいですか?
dot -Gconcentrate=true
を実行するか、エッジを分割または結合したい場所に小さな円として描画する独自の仮想ノードを導入できます。
digraph G {
yourvirtualnode [shape=circle,width=.01,height=.01,label=""]
a -> yourvirtualnode [arrowhead=none]
yourvirtualnode -> {b;c}
}
グラフレイアウトをPDFで生成するにはどうすればよいですか?
使用している Graphviz に cairo/pango のサポートがある場合は、-Tpdf
フラグを使用できます。残念ながら、これは埋め込みリンクを処理しません。
埋め込みリンクが必要な場合、または cairo/pango がない場合は、PostScript 出力を作成し、PostScript から PDF への外部コンバーターを使用します。たとえば、dot -Tps | epsf2pdf -o file.pdf
です。クリック可能な PDF オブジェクトを許可するために、URL タグが尊重されることに注意してください。
図を pdflatex などのドキュメント準備システムで PDF として使用することを目的とする場合、-Tps
ではなく -Tps2
を使用する事が非常に重要です。一般的に、本当に PDF 出力が必要な場合、つまり -Tpdf
フラグが必要な場合は、PDF に変換する前に -Tps2
を使用してください。
下の図では、網掛けされたノードには不正な出力が含まれます。
重複ノードを作成するにはどうすればよいですか?
重複したラベルを持つ一意のノードを作成します。
digraph G {
node001 [label = "A"]
node002 [label = "A"]
node001 -> node002
}
グラフまたはクラスタのラベルを、それがすべてのサブクラスタに伝播しないように設定するにはどうすればよいですか?
ラベルはグラフの終わり(閉じ括弧の後)、そのすべてのコンテンツが定義された後に設定します。(継承されない属性設定のための特別な構文を定義することが望ましいことは認めます。)
neatoで複数の平行エッジを描画するにはどうすればよいですか?
splines 属性が false の場合(デフォルト)、マルチエッジは単純に湾曲したエッジの紡錘として描画されます。介在するノードを回避しようとする試みはありません。
splines=true または polyline の場合、マルチエッジはほぼ平行なスプラインまたはポリラインとして描画されます。これは、ノードの重複がないことを前提としています。
場合によっては十分な追加のテクニックとして、カラーリストを使用してエッジに複数の色を指定することができます。これにより、それぞれ指定された色で、密接に平行なスプラインのセットが生成されます。詳細については、color 属性を参照してください。
ツリーレイアウトを対称化(バランス調整)するにはどうすればよいですか?
ツリーノードが偶数個の子を持つ場合、必ずしも中央の2つのノードの上に中心に配置されるとは限りません。子ノードの順序がわかっている場合は、新しい見えない中間ノードを導入してレイアウトのバランスを再調整する簡単な方法があります。接続エッジも不可視にする必要があります。例:
digraph G {
a -> b0
xb [label="",width=.1,style=invis]
a -> xb [style=invis]
a -> b1
{rank=same b0 -> xb -> b1 [style=invis]}
b0 -> c0
xc [label="",width=.1,style=invis]
b0 -> xc [style=invis]
b0 -> c1
{rank=same c0 -> xc -> c1 [style=invis]}
}
このテクニックは、ソルバーに組み込まれ(子ノードの順序に依存せず、ツリー以外のレイアウトでも使用可能になるべきです)。
発見したバグや問題を報告するにはどうすればよいですか?
Graphviz のバグや問題を報告または閲覧するには、Graphviz のIssues ページにアクセスしてください。
クラスタ
クラスタボックス間にエッジを作成するにはどうすればよいですか?
これは Graphviz バージョン 1.7 以降でのみ機能します。クラスタ間のエッジを作成するには、まずグラフ属性 compound=true
を設定します。次に、論理的なヘッドまたはテールとして名前でクラスタを指定できます。これにより、2つのノードを接続するエッジが、指定されたクラスタの周りのボックスの外側にクリップされます。
例:
digraph G {
compound=true; nodesep=1.0;
subgraph cluster_A {
a -> b; a -> c;
}
subgraph cluster_B {
d -> e; f -> e;
}
a -> e [ ltail=cluster_A, lhead=cluster_B ];
}
は、cluster_A
から cluster_B
に伸びるエッジを持っています。代わりに、以下のように指定すると
a -> e [ltail=cluster_A];
cluster_A
からノード e
へのエッジが作成されます。または、lhead
属性を指定することもできます。論理ノードとして指定されたクラスタが定義されていない場合、プログラムは警告を発します。また、クラスタがエッジの論理ヘッドとして指定されている場合、実際のヘッドはクラスタに含まれていなければならず、実際のテールは含まれていなければなりません。論理テールについても同様のチェックが行われます。これらの場合、エッジは通常どおり実際のノード間に描画されます。
クラスタが見づらいです。
クラスタで bgcolor=grey
(またはその他のカラー)を設定します。
出力
高品質(アンチエイリアス)の出力を得るにはどうすればよいですか?
最も簡単な方法は、PDF、SVG、PostScript などのベクターベースの出力形式を使用することです。さらに、Graphviz に cairo/pango バックエンドがある場合、アンチエイリアシングされた出力が生成されます。
別の方法として、PostScript でレイアウトを作成し(オプション -Tps
)、アンチエイリアシングを有効にして Ghostview で実行します。重要なコマンドラインオプションは次のとおりです。
-dTextAlphaBits=4
-dGraphicsAlphaBits=4
(4 は許可されるアンチエイリアシングの最高レベルです。Ghostview のドキュメントを参照してください)。
ラスターをレンダリングする完全なコマンドラインは、次のようになります。
$ gs -q -dNOPAUSE -dBATCH -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=png16m -sOutputFile=file.png file.ps
Mac OS X では、pixelglow ポートは Apple の Quartz レンダラーを使用するため、アンチエイリアシングが有効になります。また、ユーザーインターフェースに美しいドキュメントコンテナも提供します。(欠点の1つは、Mac に 3D グラフィックスがある場合、Quartz がレンダリングを高速化するためにこのリソースを取得しようとするため、Pixelglow Graphviz を Web サーバーやその他のバックグラウンドプロセスとして実行できないことです。)
11x17インチの出力しか得られません。
私たちのせいではありません!おそらくプリンターの設定です。これを信じられない場合は、dot -Tps
を実行して BoundingBox ヘッダーを確認してください。座標は 1/72 インチです。
ラベルに特別な記号やアクセント記号を作成するにはどうすればよいですか?
記号を直接(コピー/ペーストなどを使用して)dot ソースに挿入し、UTF-8 で保存します(例:)。
graph G {
yen [label="¥"]
}
UTF-8 で保存できない場合は、HTML エンティティ(例:円の通貨記号 ¥ には ¥
)を試してください。例:
graph G {
yen [label="¥"]
}
より一般的に、ASCII以外の文字セットを使用するにはどうすればよいですか?
以下は、Graphviz 2.8 以降に適用されます。(古いバージョンの Graphviz では、入力ストリームに Latin-1 またはその他の UTF-8 文字を配置するだけで済む場合がありますが、結果は必ずしも正しくありません。)
入力:一般的な考え方は、必要なグリフのUnicode値を見つけ、テキスト文字列"..."
またはHTMLのようなラベル<...>
に入力することです。
たとえば、数学の全称記号∀
の値は0x2200
です。これをファイルに挿入するにはいくつかの方法があります。1つはASCII表現を書き出すことです:&#<nnn>;
ここで<nnn>
は値の10進数表現です。0x2200
の10進値は8704
なので、文字は∀
として指定できます。あるいは、Graphviz は UTF-8 エンコードされた入力を受け入れます。forall の場合、その UTF-8 表現は 10 進値が 226
136
128
である 3 バイトです。便宜上、おそらく選択した文字セットに合わせて調整されたお気に入りのエディターを使用してこれを入力します。次に、iconv プログラムを使用して、グラフをお使いの文字セットから UTF-8 または Latin-1 にマップできます。
FaqSymbolsで提案されているように、Latin-1 文字のHTMLシンボル名も受け入れます。たとえば、セント記号(Unicode と Latin-1 の値は 10 進数 162)は ¢
として挿入できます。
グラフファイルは常にプレーンテキストドキュメントでなければならず、Word またはその他のリッチフォーマットファイルではありません。"..."
または<...>
で囲まれていない文字は、通常のASCII文字でなければなりません。特に、digraph
やsubgraph
などのすべてのDOTキーワードはASCIIでなければなりません。
エンコーディングを常に推測できないため、グラフ属性 charset
をUTF-8、Latin1(別名 ISO-8859-1 または ISO-IR-100)、またはBig-5(繁体字中国語用)に設定する必要があります。これは、グラフファイルまたはコマンドラインで行うことができます。たとえば、charset=Latin1
です。
出力:指定した文字のグリフを持つフォントが最終レンダリング時に使用可能であることが不可欠です。このフォントの選択は、ターゲットコードジェネレーターによって異なります。gd ベースのラスタージェネレーター(PNG、GIFなど)の場合、Graphviz プログラムを実行しているマシンに TrueType または Type-1 フォントファイルが必要です。Graphviz が fontconfig ライブラリでビルドされている場合、指定されたフォントを見つけるために使用されます。それ以外の場合は、Graphviz はさまざまなデフォルトディレクトリでフォントを検索します。検索されるディレクトリには、fontpath
属性、関連する環境変数またはシェル変数(fontpath エントリを参照)、および既知のシステムフォントディレクトリで指定されたものがあります。表は、これらのグリフが times.ttf フォントからのものであることを示しています。fontconfig を使用すると、このフォントを指定することは困難です。Times は通常、Adobe Type1 times に解決されますが、そのページに表示されているすべてのグリフが含まれているわけではありません。
PostScript の場合、入力は UTF-8 または Latin-1 の ASCII サブセットのいずれかでなければなりません。(より一般的な解決策を探しましたが、UTF-8 と Unicode は PostScript のすべての種類のフォントタイプで異なる方法で処理されているようで、このケースバイケースをハックする時間はありません。
SVG 出力の場合、生の UTF-8(またはその他のエンコーディング)を生成されたコードに直接渡します。
カスタムシェイプを作成するにはどうすればよいですか?
1つの方法は、IMG
属性を使用して埋め込み画像と組み合わせる可能性のあるHTML ライクなラベルを使用することです。
dot ユーザーガイドで示されているように、本当にカスタムシェイプが必要な場合は、それを組み込むためのいくつかの方法があります。現時点では、PostScript または画像ファイルであるか、ソースコードを変更する必要があります。深刻な問題は、Grappa などのすべてのドライバーとインタラクティブなフロントエンドで動作するカスタムシェイプを作成できないことです。少なくとも SVG にはインタラクティブなレンダラーがあり、PostScript はインタラクティブな機能も備えた PDF に変換できます。
SVG(-Tsvg
)、PostScript(-Tps,-Tps2
)、またはラスター形式のいずれか(-Tgif, -Tpng, または -Tjpg
)を使用する場合、ファイル名で特定の画像(例:写真)をノードに読み込むことができます。例:
yournode [image="yourface.gif"];
は、ノードの内容が GIF ファイル yourface.gif
に記載されていることを示しています。image 属性は、使用するファイルを指定します。(非推奨のshapefile 属性もあります。これは image と似ていますが、ノードの形状は常にボックスになります。)
注:特に 2006 年 3 月 11 日以前のバージョンの Graphviz、特に 1.12 Graphviz 以前では、属性 shape=custom
も設定する必要があります。
-Tsvg
を使用する場合、image
は GIF、PNG、または JPEG ビットマップファイルを含むファイルの名前を指定する必要があります。ファイルの内容は SVG 出力にコピーされず、ファイル名のみがコピーされます。したがって、Graphviz SVG 出力が正しく表示されるには、画像ファイルが SVG ビューアーで使用可能である必要があります。
PostScript を使用する場合、image
はカプセル化された PostScript またはビットマップを含むファイルの名前を指定する必要があります。内容は出力ファイルにコピーされます。カプセル化された PostScript は一度だけコピーされます。画像の内容に関する制限は、外部 PostScript ファイルで以下に指定されているものと同じです。
ビットマップ出力の場合、image
はビットマップ画像を含むファイル名です。ファイルが開かれ、出力図面にコピー(およびスケーリング)されます。
このコードはまだ暫定的なものであり、インデックスカラーマップ管理におけるカラー量子化にいくつかの問題があることを認識しており、現在原因究明と修正に取り組んでいます。(代替案として`-Gtruecolor=1`を使用して32ビット内部キャンバスを試すことができますが、画像のぼやけ(情報損失?)が確認されています。)
このソフトウェアをウェブサーバーとして使用する場合、画像ファイルへのアクセスはより制限されます。SERVER_NAMEを参照してください。
PostScriptドライバ(-Tps
)を使用する場合、EPS(Encapsulated PostScript)などの外部PostScriptファイルとしてノードシェイプをインポートできます。外部ファイルは、少なくとも有効なBoundingBoxヘッダーを持ち、showpageを抑制するためのラッパーなどをインストールしないため、グラフィック状態を大幅に変更しないようにする必要があります。
外部PostScriptファイルをインポートするには、以下のように`shape`属性と`shapefile`属性を設定します。
somenode [shape=epsf, shapefile="yourfile.ps" ];
EPSFシェイプは常にそのバウンディングボックスにクリップされます。
[shape=epsf, shapefile="yourfile.ps" ]
の使用は、前のセクションで説明されている[image="yourfile.ps" ]
を使用するメカニズムによって、大部分が置き換えられています。
PostScriptドライバ(dot -Tps
)を使用する場合、シェイプ描画用のPostScriptプロシージャを定義できます。このプロシージャは、可変サイズのシェイプを描画できる必要があります。定義を含むファイルは、-lフラグを使用してコマンドライン引数として読み込むことができます。
$ dot -Tps -l yourPS.ps file.dot -o file.ps
グラフファイルでは、シェイプを次のように呼び出します。
somenode [shape=yourshape]
file.psファイルでは、塗りつぶされていないノードの場合、yourshape
のプロシージャは次のように呼び出されます。
[ 54 36 0 36 0 0 54 0 54 36 ] 4 false yourshape
ここで、現在の色はノードのpencolorです。配列にはシェイプのバウンディングポリゴンが含まれており、最初の点が最後に繰り返され、その後に点の数が続きます。現時点では、シェイプは常に長方形です。左から右へ、配列内の点は常に反時計回りに、右上の頂点から始まります。頂点数の後のブール値(ここではfalse
)は、ノードの`fill`属性の値です。座標は絶対キャンバス座標です。
fill=true
のノードの場合、上記のyourshape
の呼び出しの前に、
[ 54 36 0 36 0 0 54 0 54 36 ] 4 true yourshape
が挿入されます。ここで、現在の色はノードのfillcolor
です。
注記: 2005年9月23日以前のバージョンでは、yourshapeはノードのfill値と、色がノードのpencolorに設定された状態で一度だけ呼び出されます。
たとえば、[shape=DFDbox]
で呼び出すことができる、ありそうなシェイプファイルDFD.psの内容を以下に示します。
/xdef {exch def} bind def
/DFDbox {
10 dict begin
/fflag xdef
/sides xdef
fflag % if shape is filled
{
aload pop
newpath
moveto
1 1 sides { pop lineto } for
closepath fill
}
{
aload pop
% draw the sides
newpath
moveto
1 1 sides {
2 mod 0 ne
{moveto} % even sides
{lineto currentpoint stroke moveto} % odd sides
ifelse
} for
}
ifelse
end
} bind def
この種のカスタムシェイプは常にそのバウンディングボックスにクリップされます。shapes.cの関数`user_shape()`にフックを作成して、長方形以外のクリッピングポリゴンを決定することは難しくありません(おそらく)。誰かがこれを試してコードを提供したい場合に備えて、この機能を備えることができます。
デフォルトでは、バウンディングボックスはコンテンツの周囲に描画され、ノードラベルも描画されます。これらを削除する場合は、ノードでlabel=""
およびperipheries=0
を設定します。
ドライバ非依存のカスタムシェイプ
PostScriptを使用していない場合は、ソースコードを変更する必要があります。他のコードジェネレータは、カスタムノードシェイプを直接サポートしていません。カスタムシェイプが高レベルでドライバ非依存である場合、シェイプ名とメソッドをマッピングする配列Shapes[]
に対応するエントリを使用して、shape.cにシェイプ固有の関数(メソッド)を追加できます。メソッドインターフェースは、このファイルのコメントヘッダーで説明されています。メソッドは、シェイプを初期化(通常はテキストラベルに合うようにサイズを設定するため)、ポート名を座標にバインドする、シェイプのインスタンス内にポイントが存在するかどうかをテストする(エッジクリッピングのため)、gvrender_engine_t
構造体で提供される関数を使用してシェイプのコードを生成する、およびノードの内部にあるポートに到達するためのボックスパスを返す(存在する場合)ように定義する必要があります。
gvrender_engine_t
を介して利用可能な関数とGraphvizグラフィックモデルの詳細については、Graphvizライブラリマニュアルの第5章を参照してください。
多かれ少なかれポリゴンのように動作するシェイプは、基本的なポリゴンメソッドからブートストラップできます。たとえば、`invtri`または`tab`シェイプを参照してください。このようなシェイプは、以下に示すフィールドを持つポリゴンの記述子を使用します。
フィールド名 | 説明 | デフォルト |
---|---|---|
regular |
正多角形の場合 | FALSE |
peripheries |
ボーダーの外周の数 | 1 |
sides |
辺の数(曲線の場合1) | 4 |
orientation |
角度回転(度) | 0 |
distortion |
台形歪み | 0 |
skew |
平行四辺形歪み | 0 |
オプション |
高度なオプション: ROUNDED、DIAGONALS、AUXLABELS | 0 |
一般的なポリゴンから派生しないシェイプについては、`record`または`epsf`シェイプを参照してください。
ドライバ依存のカスタムシェイプ
ドライバ固有のシェイプ(GIFやPNGアイコンなど)を実装するには、ユーザー定義シェイプを実装するドライバ関数の本体を作成する必要があります。これには、特定のドライバのlibrary_shape
関数を(まだ存在しない場合)提供し、ドライバのグラフィック関数を使用してシェイプを表示するために必要なグラフィック操作を生成することが含まれます。(Graphvizに付属するドライバは、pluginsディレクトリにあります。)
ユーザーシェイプ関数は基本的に4つの引数を受け取ります。
- カスタムシェイプ名文字列
- シェイプバウンディングポリゴンの絶対キャンバス座標
- 座標の数(現在、常に4)
- 塗りつぶしフラグ
残りはあなた次第ですが、念のため、最初に連絡してください。
描画レイヤー(オーバーレイ)を使用するにはどうすればよいですか?
layers
グラフ属性が設定されている場合、グラフは一連の色付きレイヤー、またはオーバーレイで印刷されます。(このカラーリングは他の設定を上書きします。)layers
はレイヤー名のリストを定義し、各レイヤー名は一連のセパレータ文字で区切られます。トークンは、予約語`all`を除く任意の識別子または自然数にすることができます。デフォルトでは、セパレータ文字はコロン、スペース、タブですが、これはlayersep
グラフ属性を使用して上書きできます。
ノード、エッジ、またはクラスタのlayer
属性は、特定のレイヤーでの外観を有効にします。その値は、layersグラフ属性からのレイヤーのリストを示します。これは、layerlistsep
属性からの文字列で区切られたレイヤー区間のリストで指定されます。各レイヤー区間は、単一のレイヤー名、またはlayersep
属性からのセパレータ文字列で区切られた2つのレイヤー名として記述されます。キーワード`all`は、可能なすべてのレイヤーを意味します。`all`が範囲の一部として使用される場合、その範囲は一方のトークンで境界が定められたすべてのレイヤーを示します。したがって、以下の例におけるエッジ`node2 -> node3`のレイヤー`pvt:all`は、レイヤーpvt、test、new、およびofcに対応します。`all:pvt,new,ofc`は、レイヤーlocal、pvt、new、およびofcに対応します。
例として、次のグラフ
digraph G {
layers="local:pvt:test:new:ofc";
node1 [layer="pvt"];
node2 [layer="all"];
node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
node2 -> node3 [layer="pvt:all"]; /* same as pvt:ofc */
node2 -> node4 [layer=3]; /* same as test */
}
は、以下に示す5つのレイヤーを生成します。
レイヤー1 | レイヤー2 | レイヤー3 |
---|---|---|
![]() |
![]() |
![]() |
レイヤー4 | レイヤー5 |
---|---|
![]() |
![]() |
レイヤーグラフでは、特定のノード(またはエッジ)にレイヤーの割り当てがないが、接続するエッジ(ノード)がある場合、そのレイヤーの仕様はこれらから推論されます。上記の例では、`node4`はレイヤー3のみに表示されます。これは、接続するエッジにレイヤーの割り当てが与えられたためです。ただし、レイヤー属性のないノードまたはエッジが、レイヤー属性のないエッジまたはノードと接続している場合(またはそのようなノードにエッジがない場合)、ノードまたはエッジはすべてのレイヤーに表示されます。
レイヤー属性のないノードとエッジがすべてのレイヤーに表示されるデフォルトを変更するには、
node [layer=all];
edge [layer=all];
をグラフファイルの先頭に追加します。
グラフには、出力するレイヤーを指定するlayerselect
属性を設定できます。値は、レイヤー属性と同じ具体的な構文を使用します。
現在、複数のレイヤーを単一出力ファイルに出力することは、PostScriptでのみ可能です。ただし、layerselect
属性を使用して、任意の形式で単一レイヤーを選択して出力できます。
レイヤーの色シーケンスは、配列layercolorseq
(少なくともPostScriptでは)で設定されます。最初のインデックスは1であり、各要素は3要素の色座標配列です。この配列の値を設定することで、カスタムレイヤーカラーを作成できます。
TODO
- レイヤーごとにデフォルトの色を簡単に変更し、必要に応じて個々のノードまたはエッジでユーザーが上書きできるようにします。
- レイヤーのカラーリングを完全にオフにし、描画に固有の色のみを使用します。
- 特定のサブグラフ内のノード/エッジに特定の属性を強制的に割り当てます。libgraphパーサーのフックが必要になる場合があります。セマンティクスをサポートするのは非常に簡単です。このサブグラフ内のすべてのノード/エッジに対して、このグラフの親のデフォルトとは異なるデフォルト属性を割り当てます。回避する必要があるのは、次の例で示されている問題です。
subgraph sub0 {
node [color=red];
a; b; c;
}
subgraph sub1 {
node [shape=diamond];
a; b; c;
}
sub1のデフォルトがcolor=blackであるという理由だけで、a、b、cをcolor=blackにリセットしたくありません。
レコードラベルやその他のラベルでフォントと色の変更を行うにはどうすればよいですか?
これはrecordシェイプでは不可能です。ただし、HTMLライクなラベルを使用することで実現できます。
-Tplain
形式では、スプラインがノードに触れません(矢印がありません)。
エッジは、メインスプラインと、必要に応じてノードに実際に接する矢印ヘッドとして指定されます。矢印ヘッドが指定されていない場合、エッジスプラインを描画すると、エッジとノードの間に隙間が残ります。これはバグですが、現在は機能として定着しています。回避策としては、edge [dir=none]
を設定します。エッジに矢印ヘッドがないため、スプラインの仕様は両方のノードまで到達します。
rankdir=LRの場合、dotとneatoでレコードノードの描画が異なります。
その通りです。dot -Grankdir=LR
は、recordノードを回転させて、最上位レベルのフィールドが依然としてレベルをまたいでリストされるようにします。rankdir=LR
はneatoでは効果がありません。回避策の1つは、HTMLライクなラベルを使用することです(回転しません。欠点はXMLで記述する必要があることです)。一般的に、recordノードをはるかに汎用性の高いHTMLライクなラベルに置き換えることをお勧めします。別の回避策として、recordラベルを{}で囲んで、recordの内容を回転/反回転させることができます。Scott Berkun(Microsoft Corp.)による「How To Avoid Foolish Consistency」も参照してください。
大きなグラフを複数のページに印刷するにはどうすればよいですか?
page属性は、設定されている場合、Graphvizに指定されたサイズのページの配列としてグラフを印刷するように指示します。したがって、グラフ
digraph G {
page="8.5,11";
...
}
8.5インチ×11インチのページとして出力されます。印刷すると、ページを繋ぎ合わせてグラフ全体の図を作成できます。現時点では、この機能はPostScript出力でのみ動作します。
あるいは、大きな画像を取り込み、ページサイズの断片を抽出できる様々なツールやビューアがあります。これらを印刷することができます。 ビューポート属性も参照してください。
赤いエッジがあると、PNGとGIF形式では単色の赤で表示されますが、JPEGにレンダリングされると黒い枠線が表示されます。
これはJPEGの可逆圧縮アルゴリズムによるアーティファクトです。JPEGは線画にはあまり適していません。PNGの使用を検討してください。
dottyで右クリックするとグローバルメニューが表示されますが、アイテムを選択できません。
NUMLOCKキーがオフになっていることを確認してください。既知のバグです。
dottyが合法的なdotファイルで構文エラーを報告するのはなぜですか?
dottyツールは非推奨ですが、まだ使用している人のためにこのエントリは残されています。
通常、このエラーは次のように報告されます。
>> graph parser: syntax error near line 14
>> context: >>> <<< digraph G {
>> dotty.lefty: giving up on dot
>> dotty.lefty: graph that causes dot
>> dotty.lefty: to fail has been saved in file dottybug.dot
おそらく、シェル環境(.aliasや.profileなど)に、非対話型シェルでも出力を生成するコマンドがあります。これが発生すると、これらの文字がdotパーサーへのパイプに入り、この問題を引き起こします。簡単な確認方法は、他のユーザーにも同じ問題があるかどうかを確認することです。
dottyのエッジ上の小さな円(「エッジハンドル」)を削除するにはどうすればよいですか?
dottyツールは非推奨ですが、まだ使用している人のためにこのエントリは残されています。
dotty.leftyファイルを編集し、'edgehandles' = 1;という行を'edgehandles' = 0;に変更します。およそ110行目付近です。
グラフのノードとエッジの座標をすべて持っていて、dot、neato、またはdottyを使用してレンダリングしたい場合、どのようにすればよいですか?
レイアウト属性を含むグラフをdotファイルに入れます。次にneato -n2
を実行します。例:
$ neato -n2 -Tgif file.dot -o file.gif
エッジにpos
属性が定義されていない場合、neatoは通常行うエッジルーティングを実行することに注意してください。通常のバックエンド属性(size
、overlap
、page
など)はすべて使用できます。
ノードの座標をすべて持っていて、dotまたはneatoでエッジをルーティングさせたいです。
neato -n
を実行します。これにより、必要なエッジ情報が追加されます。
グラフのノードとエッジの座標をすべて持っていて、dottyを使用してレンダリングしたい場合、どのようにすればよいですか?
先にレイアウトを行いたい場合は、出力形式に-Txdot
を使用します。Dottyはそこに提供されたレイアウト情報を使用します。
上記と同じですが、ノードの座標しかありません。エッジはありません。
neato -Txdot -n
を実行します。これにより、必要なエッジ情報が追加されます。
クライアント側のイメージマップを作成するにはどうすればよいですか?
-Tcmapx
コマンドラインオプションを使用します。詳細については、こちらを参照してください。
サーバー側のマップが認識されません。HTMLを確認しました!
サーバーでマップファイルが有効になっていることを確認してください。たとえば、Apacheを実行している場合は、httpd.confに次の行があることを確認してください。
AddHandler imap-file map
そして、それがコメントアウトされていないことを確認してください!
Debian Graphvizをインストールしましたが、コマンドラインでは正常に動作しますが、Apacheを介してPerl/CGIスクリプトを実行すると、出力が生成されません。
たとえば、コードsystem("/usr/local/bin/dot -Tpng /tmp/tree.dot -o /tmp/tree.png");
では、/tmp/tree.png
ファイルは生成されません。
私たちが知る限り、dotは、HOMEが設定されていないApache cgiプログラムから実行された場合、Debianシステムではstdoutまたはstderrメッセージなしで終了します。回避策は、ApacheユーザーIDの環境にHOMEディレクトリを提供することです。
GraphvizのPerlモジュールを使用することを提案した人もいます。
DreamworksのGreg Brauerは、別の可能性を指摘しました。問題は、dotを実行する前に一時的なdotファイルのファイル記述子を閉じていなかったことでした。Graphvizは、ファイルへの書き込みバッファがフラッシュされる前に、空の新しいファイルを取得することになります。dotは喜んでそれに対して実行され、警告なしに空の出力ファイルを生成します。
3D出力を得るにはどうすればよいですか?
Graphvizの開発者は、無用な3Dの使用に懸念を持っています。
それにもかかわらず、dot -Tvrml
はVRMLファイルを生成します。Z座標レイアウトはありません-ノードのz属性で自分でZ座標を指定し、エッジのZ座標は補間されます。より新しい、より有用な形式(OpenGL Performerシーングラフ?Open Scene Graphs?Java3Dプログラム?)のドライバを提供してくれる人がいれば、試してみたいと思います。
neatoは、dimおよびdimen属性(例:neato -Gdim=7
)を通じて、内部的に高次元でのレイアウトをサポートしています。Graphvizの出力は2Dと3Dを処理しますが、neatoをライブラリとして呼び出してND_pos(n)[i]
(nは関連ノードへのポインタ)を検査しない限り、高次元の出力を取得する方法はありません。
問題
neatoでノードの重なりを避けるにはどうすればよいですか?
overlapグラフ属性を使用します。
neatoでノードとエッジの重なりを避けるにはどうすればよいですか?
overlap
属性を使用してノード間にスペースを残し、-Gsplines=true
を使用します。
$ neato -Goverlap=... -Gsplines=true -Gsep=.1
sep
引数は、ノードのバウンディングボックスの比率としてのノードとエッジの分離です。つまり、sep=.1
は、各ノードが実際よりも1.1倍大きいと見なされることを意味します。実際の値には調整が必要になる場合があります。(なぜこれが定数ではないのか尋ねないでください!)このオプションはneatoを非常に遅くするため、控えめに使用し、中規模のグラフでのみ使用する必要があります。
クラッシュの原因は何ですか?
これは通常、Graphvizライブラリがstdioライブラリの1つのバージョンを使用してビルドされ、ユーザーのプログラムが別のバージョンを使用してコンパイルされた場合に発生します。stdioのFILE
構造体が異なる場合、agread()
への呼び出しによってクラッシュが発生します。これは、Visual Studioの1つのバージョンでビルドされたバイナリリリースのみを提供し、stdioはVisual Studioのバージョンによって変わるWindowsでの主な問題です。cygwinなど、互換性のないstdioを使用する可能性のあるものを使用しようとすると、発生することもあります。
最も簡単な解決策は、グラフ全体をメモリに読み込み、そのメモリへのポインタをagmemread()
に渡すことです。
それが不可能な場合(たとえば、ファイルが大きすぎる場合)、agread()
に、渡したストリームと互換性のあるリーダーを使用するように指示する必要があります。デフォルトでは、agread
は、Graphvizのコンパイルに使用されたstdioのバージョンによって生成されたFILE*
を渡していると仮定し、そのバージョンのfgets
を使用してストリームを読み取ります。独自のリーダーを渡すには、3番目の引数を使用します。
Agdisc_t mydisc;
Agodisc_t myiodisc;
mydisc.mem = NULL; // use system default
mydisc.id = NULL; // use system default
mydisc.io = &myiodisc;
myiodisc.afread = reader;
myiodisc.putstr = NULL; // only need to set if calling gvRender()
myiodisc.flush = NULL; // only need to set if calling gvRender()
リーダー関数の型は
int (*reader) (void *chan, char *buf, int bufsize);
であり、read()
システムコールのように動作する必要があります。つまり、ストリームchan
から読み取り、サイズがbufsize
であるbuf
にバイトを格納し、読み取ったバイト数を返します。
Unixライクなstdioの場合、次を使用できます。
static int reader(void *chan, char *buf, int bufsize)
{
return fread(buf, 1, bufsize, (FILE*)chan);
}
次に、グラフを読み取るには、次を使用します。
FILE* fp = fopen ("mygraph.gv","r");
Agraph_t* g = agread (fp, &mydisc);
Neatoが特定の例で無限に実行されます。
まず、グラフのサイズはどれくらいですか?Neatoは二次アルゴリズムであり、統計的多次元尺度法とほぼ同等です。数千個のノードとエッジを持つグラフを入力すると、数時間または数日かかることがあります。最初に確認する必要があるのは、neato -v
を実行して出力のトレースを取得することです。表示される数値が全体的に小さくなっている場合、レイアウトに時間がかかっているだけです。レイアウトの品質を犠牲にして、レイアウト時間を短縮するために、epsilon
やmaxiter
などの特定のパラメータを設定できます。しかし、グラフが大きい場合、誰が気づくでしょうか?
あるいは、sfdpを使用してグラフのレイアウトを行うことができます(ただし、現時点ではsfdpはエッジの長さを尊重しません)。
neatoまたは古いバージョンでmode=KK
を使用する場合、最適化が循環する可能性があります。数値が繰り返されている、または上下に変動している場合は、特にグラフが小さい場合は、neatoが循環しています。これは、1.13以降のバージョンではデフォルトでは発生しません。発生する場合は、バグとして報告してください。
古いバージョンのneatoを使用している場合、またはmode=KK
を使用した場合、循環は実際には発生する可能性があります。この循環は、初期レイアウトに非常に敏感です。start属性を使用することで、たとえば
$ neato -Gstart=3
$ neato -Gstart=rand
循環はほとんど消えるでしょう。または、大きなグラフに使用されるパラメータを使用して、レイアウトを早期に停止することもできます。
$ neato -Gepsilon=.01
$ neato -Gmaxiter=500
大きなグラフの場合、スプラインとしてのエッジの生成は三次アルゴリズムであるため、splines=true
の使用を避けることをお勧めします。(このコメントはcirco、fdp、twopiにも適用されます。)
dotのエッジラベルの配置が悪い場合、またはレイアウトが非常に複雑な場合。
デフォルトでは、dotのエッジラベルはダミーノードとしてモデル化されています。これにより、ラベルに十分なスペースが保証されますが、複雑なグラフの場合、レイアウトが大幅に歪む可能性があります。この場合、エッジラベルをxlabel
に置き換える価値があります。この場合、エッジがルーティングされた後にラベルが追加されるため、エッジラベルがないかのようにグラフがレイアウトされます。これにより、エッジラベルが重なる可能性があるという犠牲を払って、歪んだ図面を防ぐことができます。
Dotが特定の例で無限に実行されます。
dot -v
を試して、その進捗状況を観察してください。
レイアウトや解析でさえ、入力サイズに対して二次になるグラフを作成できることに注意してください。たとえば、dotでは、
digraph G {
a -> b -> c -> .... -> x -> y -> z
a -> z
b -> z
c -> z
/* and so on... */
x -> z
}
ランク付けされたグラフとしてのこれの総エッジ長(したがってレイアウト時間)は、ノードの数に対して二次です。次のことは起こらないかもしれませんが、グラフがロードされた後にノードとエッジに属性を追加することで、属性の数に対して二次時間のかかるグラフを構築することも可能です。たとえば
digraph G {
/* really big graph goes here...with N+1 nodes */
n0 -> n1 -> ... -> nN;
n0 [attr0="whatever",
attr1="something else",
/* and so on with many more attributes */
attrM="something again"]
}
属性が最初に表示されると、各オブジェクトは、以前に宣言された属性の数に比例する可能性のあるコストで訪問されます。したがって、上記のランニングタイムは、ある定数cに対してcN*O(M)
になります。これについて懸念がある場合は、ノードやエッジを宣言する前に、グラフで最初に属性を指定する必要があります。実際には、この問題は無視できます。
Twopiが特定の例で無限に実行されます。
グラフが大きく(数千のエッジ)、splines=true
を設定した場合、それらのスプラインすべてを適合させるのに多くのサイクルがかかります!
Neatoに不要なエッジ交差がある場合、またははるかに優れたレイアウトを作成する明らかな機会を逃している場合。
Neatoおよび同様の仮想物理モデルアルゴリズムは、最適化問題のヒューリスティックな解決策に依存しています。解決策が良いほど、見つけるのに時間がかかります。残念ながら、これらのヒューリスティックが局所的最小値に陥る可能性もあります。また、ノードの初期位置の影響を大きく受けます。neatoを再度実行しても、ランダムシード値が異なったり、反復回数が多くなったりすると、より良いレイアウトが得られる可能性があります。たとえば
$ neato -Gstart=5 file.dot -Tps -o file.ps
$ neato -Gepsilon=.0000001 file.dot -Tps -o file.ps
neatoのデフォルトのストレスマジョライゼーションモードでは、-Gstart=self
を使用すると、より良い初期レイアウトを作成するのに役立ちます。
neatoが平面グラフの平面レイアウトを作成する、またはグラフの対称性のすべてまたはほとんどを公開するという保証はないことに注意してください。
Webdotが機能しません。
Apacheを使用していて、TCLがインストールされていると仮定します。そうでない場合は、webdot perlスクリプトを使用する方が良いでしょう。
webdotをデバッグするには、最初にtclshがTcldot共有ライブラリをロードできるかどうかをテストします。試してみてください。
$ tclsh
% load $prefix/lib/graphviz/tcl/libtcldot.so.0
%
ここで、$prefix
はgraphvizのインストールプレフィックスです。通常は/usrまたは/usr/localです。
次に、シェルコマンドからwebdotが実行されるかどうかをテストします。(webdotでは、Apacheが提供する環境を設定するヘルパースクリプトscaffold.tclまたはscaffold.shを提供しています。)たとえば
$ scaffold.tcl >out.gif
can't read "LIBTCLDOT": no such variable
while executing
"file mtime $LIBTCLDOT"
invoked from within
"set t1 [file mtime $LIBTCLDOT]"
(file "cgi-bin/webdot" line 67)
invoked from within
"source cgi-bin/webdot
"
(file "scaffold.tcl" line 22)
上記は、webdotが正しく構成されていないことを示す強力な手がかりです。
最後に、webdotがcgi-binプログラムとして実行されるかどうかをテストします。単純なcgi-bin tclスクリプトを使用してcgi-bin環境を調べるのに役立つ場合があります。
#!/bin/env tclsh
puts "Content-type: text/plain"
puts ""
foreach e [lsort [array names env]] {puts "$e: $env($e)"}
このスクリプトを... /cgi-bin/test.tclとして保存し、実行可能にしてから、http://localhost/cgi-bin/test.tclを確認します。
また、次のようなものが見られる場合
WebDot Error:
Response Code = 403
これは通常、webdotが正常に実行されたが、引数として指定したURLからリモートグラフを取得できなかったことを意味します。理由は、サーバーがwebdotサーバーをブロックするファイアウォールの背後にある可能性が高いため、グラフファイルを取得できません。ファイアウォールのアクセス許可を変更するか、グラフを別のサーバーに配置するか、webdotをローカルにインストールして、グラフデータを取得するためにリモートサーバーを必要としないようにすることができます。
誰かがwebdotをハックして、グラフの内容をcgi-bin引数として受け入れるようにすれば、リモートでグラフを取得する権限が不要になるでしょう。これはオープンソースコミュニティへの課題として残されています。
「フォントが見つかりません」エラーが発生するか、webdotでテキストラベルが欠落しています。
まず、最近のバージョンのgraphvizは、プラットフォームで使用可能な場合、fontconfigを使用します。fontconfigを使用すると、このエラーは発生しないため、graphvizのアップグレードが利用可能かどうか、または再ビルドでfontconfigのサポートが追加されるかどうかを確認することをお勧めします。
fontconfigが使用できない場合、graphvizはフォント名をフォントパスに自分で解決しようと試み、DOTFONTPATH(またはGDFONTPATH)を使用して、検索する場所を示します。
著作権上の理由から、Graphvizには独自のフォントが付属していません。Windowsマシンでは、C:\Windows\Fontsを検索することを認識しています。Unixマシンでは、Truetypeフォントを含むディレクトリを設定する必要があります。いくつかのフォントのコピーをここで入手できます。
デフォルトのDOTFONTPATHは
#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1"
フォントが別の場所にある場合は、webdotスクリプトでそのディレクトリを設定するか、正しいDEFAULT_FONTPATHを使用してGraphvizを再コンパイルする必要があります(または、レイアウトするすべてのグラフでset fontpath="/your/font/directory"
を設定しますが、それはかなり面倒です)。
/var/www/cgi-bin/webdotで#set SIGNATURE "Graph by WebDot"
行をコメントアウトすることもできます。
グラフbbと.png画像間の座標変換は何ですか?
- bb は、有限の線幅を考慮するために、全方向に4グラフ単位(パッド)拡張されます。
- 次に、
-Gviewport
、-Gsize
、-Glandscape
、-Gorientation
オプションに従って、ズームおよび/または回転されます。デフォルトの1:1スケーリングでは、1グラフ単位 = 1ポイント(1/72インチ)です。 - 次に、
-Gpage
で要求され、出力形式がサポートしている場合にページ分割されます。ただし、-Tpng
レンダラーはまだ対応していません。 - 次に、絶対単位(インチ)でマージンが追加されます (
-Gmargin
)。上/下マージンは、左/右マージンとは別に設定できます。 - 次に、
-Gdpi
、または出力デバイスによって指定されたdpi値、または各レンダラーによって提供されるデフォルト値に従って、デバイス単位に変換されます。非正方形ピクセルを許容するために、xとyで別々のdpi値があります。一部のレンダラーはY軸を反転し、原点を左上に配置するためにオフセットが必要です。-Tpng
のデフォルトのdpiは96dpi(ほとんどのコンピューターモニターの解像度を近似)であるため、これが96/72(4/3)によるスケーリングの由来です。
レンダラーAPIでは、プラグインは座標表現を選択できます。
- グラフ単位の座標、およびスケーリング、回転、平行移動からなる合成変換データ。(svg、cairo、psレンダラーで使用)
- デバイス単位に事前に変換された座標。