Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic shapes question #290

Open
piotr-sokolowski opened this issue Sep 21, 2020 · 12 comments
Open

Generic shapes question #290

piotr-sokolowski opened this issue Sep 21, 2020 · 12 comments

Comments

@piotr-sokolowski
Copy link

Do you plan to support more generic node types like for example simple shapes ?
This would allow to use diagrams when none of existing specific nodes really match like when creating process or algorithm block diagram

@craighurley
Copy link

I would like to create a simple diagram to describe relationships between AWS accounts and it appears there is no generic box.

@steschuser
Copy link

How would a generic box look like?
If you have icons I'll try to include it.

@wolfspyre
Copy link
Contributor

i’d imagine (LMK if i’m misinterpreting) the desired behavior would be that one could create a cluster-like visual bounding container to represent that some amalgam of resources are physically or logically connected..

the use cases for such a primitive are myriad. the datacenter, subnet, and rack node types are examples that come immediately to my mind

@steschuser
Copy link

well, if you can link me some nice looking shapes that are free to use Id be happy to include them..

@ludwigm
Copy link

ludwigm commented Oct 21, 2020

I am also in need for exactly this.

The question for me would be if it really needs to be a png shape? It would be awesome to use all what diagrams offers with the additional shape options of graphviz. Happy to have that only limited to a rectangle with text to start with:
https://graphviz.org/doc/info/shapes.html

Is there anything speaking against this? :)

Thanks.

@clayms
Copy link

clayms commented Oct 26, 2020

If all you want is a box with text, you can just use the Custom node class and pass in an empty string as your node image.

from diagrams import Diagram
from diagrams.custom import Custom

with Diagram("\nCustom", show=False) as diag:
    Custom_1 = Custom("My\nCustom\ntext #1\n\n\nHELLO", "")
    Custom_2 = Custom("My 2nd\nCustom\nstring\n\n\nWORLD!", "")

    Custom_1 >> Edge(label="WEEE!!!") >> Custom_2
 
diag

image

@clayms
Copy link

clayms commented Oct 27, 2020

As a longer term solution, I would suggest adding a Polygon node class, that behaves similar to the Custom node class, with the additional option to pass in the following keyword arguments:

  1. sides,
  2. distortion,
  3. orientation,
  4. skew,
  5. color

Have a look at this Graphviz example: https://www.graphviz.org/Gallery/directed/crazy.html

@clayms
Copy link

clayms commented Oct 31, 2020

@steschuser @ludwigm @wolfspyre @craighurley

You can use all of the Graphviz shapes with the Node class. See code and output below.
https://graphviz.gitlab.io/doc/info/shapes.html

Additionally, all of the Graphviz Node attributes should also be available to you.
https://graphviz.gitlab.io/doc/info/attrs.html

from diagrams import Diagram, Node
from diagrams.custom import Custom

shapes = [
    "box","polygon","ellipse","oval","circle",
    "point","egg","triangle","plaintext","plain",
    "diamond","trapezium","parallelogram","house","pentagon",
    "hexagon","septagon","octagon","doublecircle","doubleoctagon",
    "Mdiamond","Msquare","Mcircle",
    "rect","rectangle","square","star","none","underline","cylinder",
    "tripleoctagon","invtriangle","invtrapezium","invhouse",
    "note","tab","folder","box3d","component","promoter",
    "cds","terminator","utr","primersite","restrictionsite",
    "fivepoverhang","threepoverhang","noverhang","assembly",
    "signature","insulator","ribosite","rnastab","proteasesite",
    "proteinstab","rpromoter","rarrow","larrow","lpromoter", ]

num_shapes = len(shapes)
shapes_per_row = 5
num_of_rows = int(num_shapes / shapes_per_row) + (num_shapes % shapes_per_row > 0)

with Diagram("\n\nUsing Graphviz Shapes", show=False) as diag:
    for row in range(num_of_rows)[::-1]:
        items_in_row = shapes_per_row - (row+1) * shapes_per_row // num_shapes
        shapes_i = row * shapes_per_row
        node_list = [
               'Node('
                f'shape="{shapes[shapes_i+item_num]}", '
                f'label="\\n"+"{shapes[shapes_i+item_num]}", '
                'labelloc="t", '
                'style="solid") - Edge(penwidth="0.0")'
            for item_num in range(items_in_row)[:-1]
        ] + ['Node('
                f'shape="{shapes[shapes_i+items_in_row-1]}", '
                f'label="\\n"+"{shapes[shapes_i+items_in_row-1]}", '
                'labelloc="t", '
                'style="solid")']

        node_row = "-".join(node_list)
        eval(node_row)

diag

using_graphviz_shapes

@wolfspyre
Copy link
Contributor

I for one, really appreciate all your efforts to help out here, (and all the other places where you’ve helped others, with example code even!!!) thank you, @clayms the world needs more contributors like you :)

@mingrammer - assuming you like the implementation as is, the above would be super useful as an example, and perhaps even a test to help ensure no future change unintentionally alters behavior.

@ludwigm
Copy link

ludwigm commented Nov 1, 2020

@clayms This is fantastic. I was not aware that this is possible. I totally will give this a try :)

@clayms
Copy link

clayms commented Nov 1, 2020

Here is how you can add "record" shaped Nodes and have the Edges point to specific fields of each "record" Node.

See: https://graphviz.gitlab.io/doc/info/shapes.html#record

with Diagram("\nRecord-based Nodes", show=False, direction="TB") as diag:
    TB_fields  = Node(shape="record", label="{ <t> top |<m> middle |<b> bottom }")
    TB_fields2 = Node(shape="record", label="{ <t> top |<m> middle |<b> bottom }")
    LR_fields  = Node(shape="record", label=" <f0> left|<f1> middle|<f2> right" )
    LR_fields2 = Node(shape="record", label=" <f0> left|<f1> middle|<f2> right")
    
    TB_fields  >> Edge(tailport="t", headport="b") >> TB_fields2

    LR_fields >> Edge(tailport="f2", headport="f0") >> LR_fields2

diag

image

@clayms
Copy link

clayms commented Nov 2, 2020

@mingrammer
If some form of the examples above were to be added to the documentation, which document do you prefer:

  1. examples.md
  2. node.md

I can see a case for having certain versions in both.

Regarding the Edge specific items tailport and headport, those may also be called out in edge.md.

With the ability to use all of the Graphviz node shapes, it is also possible to replicate some of the graphs from the Graphviz Gallery.

Let me know any particular preference you have and I can add them and create a pull request.

Thanks,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants