2011-11-13 34 views
20

Có thể và thiết thực cho Mathematica để vẽ một cái gì đó như thế này (được tạo ra bởi Graphviz):Làm thế nào để vẽ sơ đồ trạng thái cổ điển bằng Mathematica?

enter image description here

Đây là tốt nhất mà tôi có thể nhận được (nhưng hình dáng và phong cách không thỏa mãn):

enter image description here

Code:

GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, 
    "went"}, {C -> C, "loop"}}, VertexLabeling -> True, 
DirectedEdges -> True] 
+0

Không có lý do bạn không thể sử dụng đồ họa nguyên thủy để vẽ một cái gì đó như thế này. Bạn có yêu cầu giải pháp bố cục tự động không? –

+1

@ Mr.Wizard Có, tôi đang tìm kiếm một số cấp cao nguyên thủy để vẽ sơ đồ trạng thái phức tạp. Tôi không biết liệu Mathematica có cung cấp điều đó hay không. Tôi đã tìm kiếm thông qua tài liệu và kiểm tra các tùy chọn của hàm "GraphPlot" và kết thúc bằng mã ở trên. – Ning

+0

Tại sao bạn chấp nhận câu trả lời của tôi? Hình dạng nó vẫn sai. Tôi đánh giá cao nó, nhưng tôi nghĩ bạn nên chờ đợi một câu trả lời tốt hơn. –

Trả lời

21

Bạn có thể làm một cái gì đó như thế này bằng cách sử dụng VertexRenderingFunction.

GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}}, 
DirectedEdges -> True, 
VertexRenderingFunction -> ({{White, Disk[#, 0.15]}, 
    AbsoluteThickness[2], Circle[#, 0.15], 
    If[MatchQ[#2, A | B], Circle[#, 0.12], {}], Text[#2, #]} &)] 

enter image description here


Phương pháp Cập nhật tháng 2 năm 2015

Để duy trì khả năng tương tác sắp xếp lại đồ thị với các công cụ vẽ (double click) người ta phải giữ cho đồ họa đỉnh bên trong GraphicsComplex, với chỉ mục thay vì tọa độ. Tôi tin rằng người ta có thể làm điều này từ VertexRenderingFunction bằng cách sử dụng biến số tăng nhưng có vẻ dễ dàng hơn để thực hiện việc đó với chế độ hậu xử lý. Này hoạt động trong các phiên bản 7 và 10 của Mathematica, có lẽ 8 và 9 cũng như:

GraphPlot[ 
    {{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}}, 
    DirectedEdges -> True 
] /. 
Tooltip[Point[n_Integer], label_] :> 
    {{White, Disk[n, 0.15]}, 
    Black, AbsoluteThickness[2], Circle[n, 0.15], 
    If[MatchQ[label, A | B], Circle[n, 0.12], {}], Text[label, n]} 

enter image description here

+0

Có "VertexLabelingFunction" không? – Ning

+0

@Tôi đã gặp lỗi trong câu trả lời của mình; Tôi có nghĩa là 'VertexRenderingFunction'. Tôi không tin rằng có một Vertex ** Labeling * Funcion. Ngoài ra, tôi nhận thấy rằng tôi đã có một lỗ hổng trong đồ họa của tôi so với ví dụ ban đầu của bạn về kích thước vòng tròn. Tôi sửa chữa đây là phiên bản thứ hai tôi chỉ cần đưa lên. –

5

Không cần cho vị trí tương tác để có được đỉnh của bạn tại vị trí mong muốn như mr.Wizard gợi ý trong his answer. Bạn có thể sử dụng VertexCoordinateRules cho rằng:

GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}}, 
    DirectedEdges -> True, 
    VertexRenderingFunction -> 
      ({{White, Disk[#, 0.15]}, AbsoluteThickness[2], Circle[#, 0.15], 
      If[MatchQ[#2, A | B], Circle[#, 0.12], {}], Text[#2, #]} &), 
    VertexCoordinateRules -> 
      {A -> {0, 0}, C -> {0.75, 0},B -> {1.5, 0.25}, D -> {1.5, -0.25}} 
] 

enter image description here

+0

Tôi không có nghĩa là cần thiết phải có bố cục tương tác, nhưng tôi có thể thấy cách suy luận đó có thể được suy ra như thế nào. Phương pháp này cũng hoạt động. Bạn có biết cách nào để bảo toàn khả năng chỉnh sửa bên cạnh một biến thể của hack tôi đã sử dụng không? –

+0

@ Mr.Wizard Tôi không thấy một lối thoát dễ dàng. –

Các vấn đề liên quan