Skip to main content

graphics - How to draw block diagrams as Graph objects?


In the documentation ClosedLoopResponsesWithAPIDController, There is a very nice block diagram. I want to create my own block diagrams similar to this. I clicked on the diagram and pressed "command-shift-E" to show the underlying expression. I found the expression below. While this is explicit and reasonably easy to modify and extend, For really big graphs (which I have) it will rapidly become too difficult to manage by hand. I wonder if there is an easier way to produce such graphics? Is there a tool I just don't know about for drawing and / or automatically laying out such things?


Graph[{1, 2, 3, 4, 5, 6, 7, 8, 

9}, {{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}, {6,
2}, {8, 4}, {9, 6}}, Null}, {
EdgeLabels -> {DirectedEdge[8, 4] -> Placed[
Style["+", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], {1, {-0.8, 0.2}}],
DirectedEdge[3, 4] -> Placed[
Style["+", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], 0.9],
DirectedEdge[9, 6] -> Placed[
Style["+", {FontFamily -> "Helvetica",

GrayLevel[0, 1], 12}], {1, {-0.8, 0.2}}],
DirectedEdge[5, 6] -> Placed[
Style["+", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], 0.9],
DirectedEdge[6, 2] -> Placed[
Style["-", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], {0.965, {-0.7, 0}}],
DirectedEdge[1, 2] -> Placed[
Style["+", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], 0.9]},

EdgeShapeFunction -> {},
EdgeStyle -> {
GrayLevel[0, 1]}, Epilog -> {
Text[
Style["u", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], {2.5, 0.1}]},
ImageSize -> 500,
VertexCoordinates -> {{0., 0.}, {0.7, 0.}, {1.8, 0.}, {2.9,
0.}, {3.9, 0.}, {5., 0.}, {5.6, 0.}, {
2.9, 0.66}, {5., 0.66}}, VertexLabels -> {1 -> Placed[

Style["r", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 6 -> Placed[
Style["", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 9 -> Placed[
Style["m", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 2 -> Placed[
Style["", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 8 -> Placed[
Style["d", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 7 -> Placed[

Style["y", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 3 -> Placed[
Style["PID controller", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 4 -> Placed[
Style["", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center], 5 -> Placed[
Style["linear system", {FontFamily -> "Helvetica",
GrayLevel[0, 1], 12}], Center]},
VertexShapeFunction -> {
3 -> "Square", 4 -> "Circle", 7 -> "Square",

5 -> "Square", 9 -> "Square", 1 -> "Square", 6 ->
"Circle", 8 -> "Square", 2 -> "Circle"},
VertexSize -> {8 -> {0.1, 0.1}, 3 -> {0.6, 0.2},
2 -> {0.125, 0.125}, 1 -> {0.1, 0.1}, 9 -> {0.1, 0.1},
4 -> {0.125, 0.125}, 6 -> {0.125, 0.125},
5 -> {0.6, 0.2}, 7 -> {0.1, 0.1}},
VertexStyle ->
{2 -> Directive[GrayLevel[1],
EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
1 -> Directive[Opacity[0], EdgeForm[{}]],

8 -> Directive[Opacity[0], EdgeForm[{}]],
7 -> Directive[Opacity[0], EdgeForm[{}]],
5 -> Directive[GrayLevel[1],
EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
6 -> Directive[GrayLevel[1],
EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
4 -> Directive[GrayLevel[1],
EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
9 -> Directive[Opacity[0], EdgeForm[{}]],
3 -> Directive[GrayLevel[1],

EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]]
}}]

Answer



A little more summarized, but still extensive:


aL=25(*ArrowLenght*);rC=5(*RadiusCircle*);rL=34(*RectangleLenght*);
sequence={aL,2rC,aL,rL,aL,2rC,aL,rL,aL,2rC,aL};
accSequence=Prepend[Accumulate[sequence],0];

rect=MapThread[{Rectangle[{accSequence[[#1]],-7},{accSequence[[#2]],7}],
Text[Style[#3,10,Bold,Red],{accSequence[[#1]]+rL/2,0}]}&,{{4,8},{5,9},{"PIDController","LinearSystem"}}];


line1=Line[{{accSequence[[7]],0},{accSequence[[8]],0}}];

circles=Circle[{accSequence[[#]]+rC,0},5]&/@{2,6,10};

arrowsH=
MapThread[{{accSequence[[#]],0},{accSequence[[#2]],0}}&,{{1,4,5,9,11},{2,3,6,10,12}}];

arrowsV=
MapThread[{{accSequence[[#]]+rC,#2+aL},{accSequence[[#]]+rC,#2}}&,{{6,10},{rC,rC}}];


arrows=Join[arrowsH,arrowsV];

texts={
Text[Style["r",12],{accSequence[[1]]-2,0}],
Text[Style["u",12],{accSequence[[5]]+aL/2,4}],
Text[Style["d",12],{accSequence[[6]]+rC,33}],
Text[Style["m",12],{accSequence[[10]]+rC,33}],
Text[Style["y",12],{accSequence[[12]]+2,0}],
Text[Style["-",12],{accSequence[[3]]+4,4}],

Text[Style["+",12],{accSequence[[#]]-4,4}]&/@{2,6,10},
Text[Style["+",12],{accSequence[[#]]+4,4}]&/@{7,11}
};

Graphics[{texts,circles,line1,,Arrowheads[0.02],
Arrow[#]&/@arrows,EdgeForm[Black],LightGray,rect}]

enter image description here


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]