常見問題

如果您在此處找不到問題的答案,請在 Graphviz 論壇中提出您的問題。


一般

在哪裡可以找到控制 dot 或 neato 的所有屬性清單?

請參閱圖形屬性。另有關於命令列用法輸出格式的資訊。

在哪裡可以討論 Graphviz?

請在Graphviz 論壇中發佈問題和評論

我試著將版面配置放大。該怎麼做?

有多種方法可以增加佈局的大小。在執行此操作時,必須決定是否也應增加節點和文字的大小。

一種方法是調整個別參數,例如 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,增加邊緣長度將傾向於擴展佈局。

graph G {
  layout="neato"
  edge [len=3]
  a -- { b c d }
}

對於 twopi 和 circo,還有其他參數可以使用,例如 ranksep。請參閱圖形屬性

您也可以使用 ratio 屬性。如果您將 size 屬性設定為所需的繪圖大小,然後設定 ratio=fill,則節點位置會在 x 和 y 方向上單獨縮放,直到繪圖填滿指定的大小。請注意,節點大小保持不變。相反地,如果您設定 ratio=expand,則佈局會在 x 和 y 方向上均勻放大,直到至少一個維度符合大小。

如果您指定 size 屬性,但在結尾加上驚嘆號 (!),最終的繪圖會在 x 和 y 方向上均勻放大,直到至少一個維度符合大小。請注意,所有內容都會放大,包括文字和節點大小。

如果您使用 PostScript,您只需在設定 PostScript 環境的位置手動加入類似 2 2 scale 的指令,即可放大輸出。如果您的工具會查看此標頭,請務必調整 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。請注意,URL 標籤會受到尊重,以允許可點擊的 PDF 物件。

如果您的目的是在某些文件準備系統(例如 pdflatex)中使用 PDF 圖形,則使用 -Tps2 而不是 -Tps 非常重要。一般而言,如果您真的想要 PDF 輸出,也就是說,您想要擁有 -Tpdf 旗標,請先使用 -Tps2 再轉換為 PDF。

在下面的圖表中,陰影節點將包含錯誤的輸出。

alt text

如何建立重複的節點?

建立具有重複標籤的唯一節點。

digraph G {
  node001 [label = "A"]
  node002 [label = "A"]
  node001 -> node002
}

如何設定圖形或叢集標籤,使其不會傳播到所有子叢集?

在定義所有內容之後,將標籤設定在圖表的結尾(在右大括號之前)。(我們承認,為非繼承的屬性設定定義一些特殊語法似乎是可取的。)

如何在 neato 中繪製多條平行的邊緣?

當 splines 屬性為 false(這是預設值)時,多重邊緣會繪製為簡單彎曲邊緣的軸。並不會嘗試避開介入的節點。

當 splines=true 或 polyline 時,多重邊緣會繪製為大致平行的曲線或折線。這取決於沒有節點重疊。

有時足夠的另一個技巧是使用色彩清單為邊緣指定多種顏色。這會產生一組緊密平行的曲線,每條曲線都以其指定的顏色繪製。請閱讀顏色屬性以取得更多資訊。

如何使樹狀結構版面配置對稱(平衡)?

當樹狀節點具有偶數個子節點時,它不一定位於中間兩個子節點的正上方。如果您知道子節點的順序,一個簡單的技巧是引入新的、隱形的中間節點,以重新平衡佈局。連接邊緣也應該是隱形的。例如

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 的錯誤和問題。

叢集

如何建立叢集方塊之間的邊緣?

這僅在 Graphviz 1.7 版及更高版本中有效。若要在叢集之間建立邊緣,請先設定圖形屬性 compound=true。然後,您可以將叢集按名稱指定為邊緣的邏輯頭或尾。這會導致將連接兩個節點的邊緣裁剪到給定叢集周圍方塊的外部。

例如,

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_Acluster_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 轉譯器,這會啟用反鋸齒。它也為其使用者介面提供了一個美觀的文件容器。(一個缺點是,如果您的 Mac 有 3D 圖形,您無法將 Pixelglow Graphviz 作為 Web 伺服器或其他背景處理程序執行,因為 Quartz 希望取得此資源來加速轉譯。)

我只能獲得 11x17 的輸出?

這不是我們造成的!這可能是您的印表機設定。如果您不相信這一點,請執行 dot -Tps 並查看 BoundingBox 標頭。座標以 1/72 英吋為單位。

如何在標籤中建立特殊符號和重音符號?

將符號直接插入(例如透過複製/貼上)到您的 dot 原始碼中,並另存為 UTF-8,例如

graph G {
  yen [label="¥"]
}

如果您無法以 UTF-8 格式儲存,請嘗試HTML 實體,例如 Yen 貨幣符號 ¥ 的 ¥。範例

graph G {
  yen [label="¥"]
}

更普遍來說,我該如何使用非 ASCII 字元集?

以下內容適用於 Graphviz 2.8 及更新版本。(在較舊版本的 Graphviz 中,您有時可以簡單地將 Latin-1 或其他 UTF-8 字元放入輸入串流中,但結果不一定正確。)

輸入:一般概念是找到您想要的字符的Unicode 值,並將其輸入到文字字串 "..." 或類似 HTML 的標籤 <...> 中。

例如,數學「對於所有」符號 的值為 0x2200。有多種方法可以將其插入到檔案中。一種方法是寫出 ASCII 表示法:&#<nnn>;,其中 <nnn> 是值的十進位表示法。0x2200 的十進位值為 8704,因此該字元可以指定為 &#8704;。或者,Graphviz 接受 UTF-8 編碼輸入。在「對於所有」的情況下,其 UTF-8 表示法是 3 個位元組,其十進位值為 226136128。為了方便起見,您可能會使用您最喜歡的編輯器輸入,並針對您選擇的字元集進行調整。然後,您可以使用 iconv 程式將圖形從您的字元集對應到 UTF-8 或 Latin-1。

我們也接受FaqSymbols 中建議的 Latin-1 字元的 HTML 符號名稱。例如,分符號(Unicode 和 Latin-1 值十進位 162)可以插入為 &cent;

請注意,圖形檔案必須始終為純文字文件,而不是 Word 或其他豐富格式的檔案。未包含在 "..."<...> 中的任何字元都必須是一般的 ASCII 字元。尤其是,所有 DOT 關鍵字(例如 digraphsubgraph)都必須是 ASCII。

由於我們無法總是猜測編碼,因此您應該將圖形屬性 charset 設定為 UTF-8Latin1(別名 ISO-8859-1 或 ISO-IR-100)或 Big-5,以適用於繁體中文。這可以在圖形檔案中或在命令列上完成。例如,charset=Latin1

輸出:在最終轉譯時,必須提供具有指定字元字符的字型。此字型的選擇取決於目標程式碼產生器。對於基於 gd 的點陣產生器(PNG、GIF 等),您需要在執行 Graphviz 程式的電腦上使用 TrueType 或 Type-1 字型檔案。如果 Graphviz 是使用 fontconfig 程式庫建置的,則會使用它來尋找指定的字型。否則,Graphviz 會在各種預設目錄中尋找字型。要搜尋的目錄包括 fontpath 屬性、相關環境或 shell 變數(請參閱 fontpath 項目)以及已知的系統字型目錄所指定的目錄。表格指出這些字符來自 times.ttf 字型。使用 fontconfig 時,很難指定此字型。Times 通常會解析為 Adobe Type1 times,它沒有該頁面上看到的所有字符。)

對於 PostScript,輸入必須是 UTF-8 或 Latin-1 的 ASCII 子集。(我們一直在尋找更通用的解決方案,但似乎每種字型類型在 PostScript 中對 UTF-8 和 Unicode 的處理方式都不同,而且我們沒有時間逐個破解這種情況。)

對於 SVG 輸出,我們只將原始 UTF-8(或其他編碼)直接傳遞到產生的程式碼。

如何建立自訂形狀?

一種方法是使用 類似 HTML 的標籤,並可能結合使用 IMG 屬性的嵌入式影像。

dot 使用者指南中所暗示,如果您想要真正自訂的形狀,則有多種方法可以合併。此時,它們必須在 PostScript 或影像檔案中,或者您需要修改原始碼。一個嚴重的問題是,您無法製作可在所有驅動程式和互動式前端(例如 Grappa)中使用的自訂形狀。至少 SVG 具有互動式轉譯器,而 PostScript 可以轉換為 PDF,PDF 也具有一些互動功能。

外部影像檔案

如果使用 SVG (-Tsvg)、PostScript (-Tps,-Tps2) 或其中一種點陣格式 (-Tgif、-Tpng 或 -Tjpg),則可以將某些影像(例如圖片)按檔案名稱載入節點。例如

   yournode [image="yourface.gif"];

表示節點的內容在 GIF 檔案 yourface.gif 中給出。 image 屬性指定要使用的檔案。(還有已棄用的 shapefile 屬性。它與 image 類似,但節點形狀將始終為一個方塊。)

注意:在 2006 年 3 月 11 日之前的版本,特別是 1.12 graphviz 及更早的版本中,還必須設定屬性 shape=custom

使用 -Tsvg 時,image 必須提供包含 GIF、PNG 或 JPEG 位圖檔案的檔案名稱。請注意,檔案的內容不會複製到 SVG 輸出中,僅複製檔案名稱。因此,為了使 Graphviz SVG 輸出正確顯示,影像檔案必須對 SVG 檢視器可用。

使用 PostScript 時,image 必須提供包含封裝式 PostScript 或位圖的檔案名稱。內容會複製到輸出檔案中。請注意,封裝式 PostScript 只會複製一次。影像內容的限制與以下 外部 PostScript 檔案 中指定的限制相同。

對於位圖輸出,image 是一個包含位圖影像的檔案名稱。檔案會被開啟並複製(並可能縮放)到輸出繪圖中。

此程式碼仍處於初步階段,我們已注意到索引式色彩對應表管理中的一些色彩量化問題,我們正試圖理解和糾正。(您可以嘗試使用 -Gtruecolor=1 作為替代方案,使用 32 位元內部畫布,但我們觀察到影像的模糊(失真?)現象。)

當軟體用作 Web 伺服器時,對影像檔案的存取會更加受限。請參閱 SERVER_NAME。

外部 PostScript 檔案

如果使用 PostScript 驅動程式(-Tps),您可以將節點形狀匯入為外部 PostScript 檔案,例如 EPS(封裝式 PostScript)。外部檔案至少必須具有有效的 BoundingBox 標頭,並且不要對圖形狀態執行劇烈的操作,因為我們不會安裝例如阻止 showpage 的包裝函式。

若要匯入外部 PostScript 檔案,請設定 shapeshapefile 屬性,如下所示

	somenode  [shape=epsf, shapefile="yourfile.ps" ];

EPSF 形狀始終會被裁剪到其邊界框。

使用 [shape=epsf, shapefile="yourfile.ps" ] 在很大程度上已被前一節中描述的機制取代,改為使用 [image="yourfile.ps" ]

外部 PostScript 程序

如果使用 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 只會調用一次,使用節點的填滿值,並將顏色設定為節點的 pencolor。

例如,以下是一個合理的形狀檔案 DFD.ps 的內容,可以使用 [shape=DFDbox] 調用

	/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.c,並在陣列 Shapes[] 中新增相應的項目,將形狀名稱對應到方法。方法介面在此檔案的註解標頭中說明。必須定義方法來初始化形狀(通常將其調整大小以適合其文字標籤)、將埠名稱繫結到座標、測試點是否在形狀的實例內(用於邊緣裁剪)、透過 gvrender_engine_t 結構中提供的函式為形狀產生程式碼,並傳回到達節點內部埠的框路徑(如果它們存在)。

有關透過 gvrender_engine_t 提供的函式以及 Graphviz 圖形模型的更多資訊,請參閱 Graphviz 函式庫手冊的第 5 節。

行為或多或少像多邊形的形狀可以從基本多邊形方法啟動;例如,請參閱 invtritab 形狀。此類形狀使用多邊形描述符,其欄位如下所示。

欄位名稱 說明 預設值
regular 是否為規則多邊形 FALSE
peripheries 邊框外圍數量 1
sides 邊數(曲線為 1) 4
orientation 角度旋轉(以度為單位) 0
distortion 梯形失真 0
skew 平行四邊形失真 0
選項 花俏選項:ROUNDED、DIAGONALS、AUXLABELS 0

對於非衍生自一般多邊形的形狀,請參閱 recordepsf 形狀。

與驅動程式相關的自訂形狀

若要實作特定於驅動程式的形狀(例如 GIF 或 PNG 圖示),您需要為實作使用者定義形狀的驅動程式函式編寫主體。這涉及為特定驅動程式提供 library_shape 函式(如果它尚不存在),並使用驅動程式的圖形函式產生顯示您的形狀所需的圖形操作。(Graphviz 隨附的驅動程式可以在外掛程式目錄中找到。)

使用者形狀函式基本上接收四個引數

  • 自訂形狀名稱字串
  • 形狀邊界多邊形的絕對畫布座標
  • 座標數(目前,始終為 4)
  • 填滿旗標

剩下的由您決定,但請先聯絡我們。

如何使用繪圖圖層(覆蓋)?

如果設定了 layers 圖形屬性,則圖形會以一系列彩色圖層或覆蓋圖列印。(此著色會覆寫任何其他設定。)layers 定義圖層名稱的清單,每個圖層名稱以一系列分隔字元分隔。權杖可以是任何識別碼或自然數,保留字 all 除外。預設情況下,分隔字元是冒號、空格和 Tab,但可以使用 layersep 圖形屬性覆寫此設定。

節點、邊緣或叢集的 layer 屬性會使其出現在給定的圖層中。其值表示 layers 圖形屬性中的圖層清單。它由圖層間隔清單指定,這些間隔由 layerlistsep 屬性中的一系列字元分隔。每個圖層間隔都寫為單個圖層名稱,或由 layersep 屬性中的一系列分隔字元分隔的兩個圖層名稱。關鍵字 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,每個元素都是一個三元素顏色座標陣列。可以透過設定此陣列的值來建立自訂圖層顏色。

待辦事項

  • 只需變更每個圖層的預設顏色,從而在需要時允許使用者覆寫個別節點或邊緣。
  • 完全關閉圖層著色,只使用繪圖中固有的顏色。
  • 強制給定子圖中的節點/邊緣採用某些屬性。可能需要在 libgraph 剖析器中加入一個鉤子。支援以下語義將非常容易:對於此子圖中的每個節點/邊緣,將其指派給與此圖形父系預設值不同的預設屬性。您需要避免的是在以下範例中暴露的問題
  subgraph sub0 {
    node [color=red];
    a; b; c;
  }
  subgraph sub1 {
    node [shape=diamond];
    a; b; c;
  }

我們不希望僅因為 a,b,c 在 sub1 中是預設值而將它們重設為 color=black。

如何在記錄標籤或其他標籤中進行字型和顏色變更?

這在記錄形狀中是不可能的。但是,您可以使用類 HTML 標籤來完成此操作。

-Tplain 格式中,曲線不會接觸節點(箭頭遺失)。

邊緣被指定為主曲線,如有必要,還有實際鄰接節點的箭頭。如果未給出箭頭,繪製邊緣曲線會在邊緣和節點之間留下間隙。這是一個已固化為功能的錯誤。一種解決方法是設定 edge [dir=none]。由於邊緣沒有箭頭,曲線規格將一直延伸到兩個節點。

當 rankdir=LR 時,記錄節點在 dot 和 neato 中的繪製方式不同。

這是真的。dot -Grankdir=LR 會旋轉記錄節點,使其頂層欄位仍然跨層級列出。rankdir=LR 在 neato 中無效。一個解決方法是使用類 HTML 標籤(它們不會旋轉;缺點是你必須用 XML 撰寫)。一般而言,我們建議用更通用的類 HTML 標籤替換記錄節點。另一個解決方法是用 { } 括住記錄標籤來旋轉/不旋轉記錄內容。另請參閱 Scott Berkun(微軟公司)的《如何避免愚蠢的一致性》。

如何將大型圖形列印在多個頁面上?

如果設定了 page 屬性,Graphviz 會將圖表列印為指定大小的頁面陣列。因此,圖表

digraph G {
  page="8.5,11";
  ...
}

將會輸出為 8.5 x 11 英吋的頁面。列印時,這些頁面可以平鋪以繪製整個圖表。目前,此功能僅適用於 PostScript 輸出。

或者,有各種工具和檢視器可以處理大型圖片,並允許你提取頁面大小的片段,然後可以列印這些片段。另請參閱 viewport 屬性。

當我有一個紅色邊緣時,它在 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

可能是你的 shell 環境(例如 .alias 或 .profile)中有一個命令即使對於非互動式 shell 也會輸出。當這種情況發生時,這些字元會進入 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 將執行它通常會執行的任何邊緣路由。所有常見的後端屬性(sizeoverlappage 等)都可用。

我已經擁有所有節點的座標,而我希望 dot 或 neato 來路由邊緣。

執行 neato -n。這將新增必要的邊緣資訊。

我已經擁有圖形的所有節點和邊緣座標,只想使用 dotty 來渲染它。該怎麼做?

如果你想先執行佈局,請使用 -Txdot 作為輸出格式。Dotty 使用此處提供的佈局資訊。

和上面一樣,但我只有節點座標,沒有邊緣座標。

執行 neato -Txdot -n。這將新增必要的邊緣資訊。

如何建立用戶端影像地圖?

使用 -Tcmapx 命令列選項。如需更多詳細資訊,請參閱此處

為什麼我的伺服器端地圖無法被識別?我已經檢查過 HTML 了!

請確保你的伺服器已啟用 map 檔案。例如,如果執行 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

據我們所知,當從沒有設定 HOME 的 Apache cgi 程式執行時,dot 在 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 在內部透過 dimdimen 屬性支援更高維度的佈局,例如 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 程式庫建置,而使用者的程式使用另一個版本編譯時,通常會發生這種情況。如果 stdio 的 FILE 結構不同,則呼叫 agread() 會導致崩潰。這主要是 Windows 上的問題,我們只提供使用一個版本的 Visual Studio 建置的二進制版本,並且 stdio 會根據 Visual Studio 的版本而變更。如果使用者嘗試使用 cygwin 或類似的程式,也可能會發生這種情況,這些程式也可能會使用不相容的 stdio。

最簡單的解決方案是將整個圖表讀入記憶體,並將指向該記憶體的指標傳遞給 agmemread()

如果這不可能(例如,檔案太大),你需要告訴 agread() 使用與你給它的串流相容的讀取器。預設情況下,agread 假設你傳遞給它的是由用於編譯 Graphviz 的 stdio 版本產生的 FILE*,並使用該版本的 fgets 來讀取串流。若要傳遞你自己的讀取器,請使用第三個引數

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 讀取,將位元組儲存在 buf 中,其大小為 bufsize,並傳回它讀取的位元組數。

對於類 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 以取得輸出的追蹤。如果你看到的數字通常越來越小,則表示佈局只是需要很長時間。你可以設定某些參數,例如 epsilonmaxiter 來縮短佈局時間,但會犧牲佈局品質。但是如果你的圖表很大,誰會注意到?

或者,使用 sfdp 來佈局圖表(儘管目前,sfdp 不會考慮邊緣長度)。

如果你將 mode=KK 與 neato 或早期版本一起使用,則最佳化可能會循環。如果你看到數字重複或上下波動,則 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"]
}

當屬性第一次出現時,會存取每個物件,其可能的成本與先前宣告的屬性數量成正比。因此,上述執行時間將是 cN*O(M),其中 c 為某個常數。如果有任何關於此的問題,則圖表應該在宣告節點或邊緣之前先指定屬性。實際上,這個問題可以忽略不計。

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 是否能從 shell 命令執行。(在 webdot 中,我們提供了一個輔助腳本 scaffold.tcl 或 scaffold.sh,它會設定一個類似 Apache 提供的環境。)例如

$ 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 環境可能會有幫助,可以使用一個簡單的 cgi-bin tcl 腳本,例如:

#!/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/72 英寸)。
  • 然後,如果 -Gpage 要求並且輸出格式支援,則進行分頁。目前 -Tpng 渲染器還不支援。
  • 然後,以絕對單位(英寸)加入邊距 -Gmargin。頂部/底部邊距可以獨立於左/右邊距設定。
  • 然後,根據 -Gdpi 或輸出設備給定的 dpi 值,或每個渲染器提供的預設值,將其轉換為裝置單位。x 和 y 有單獨的 dpi 值,以允許非方形像素。一些渲染器會反轉 Y 軸,並且需要一個偏移量將原點放置在左上角。 -Tpng 的預設 dpi 是 96dpi(約為大多數電腦螢幕的解析度),這就是 96/72 (4/3) 縮放比例的來源。

在渲染器 api 中,外掛程式可以選擇座標表示方式

  • 圖形單位中的座標,以及由縮放、旋轉和平移組成的複合變換資料。(由 svg、cairo、ps 渲染器使用)
  • 預先轉換為裝置單位的座標。
上次修改日期:2024 年 7 月 28 日: 將所有 Hugo 的 'ref's 替換為 'relref's (bbef86a)