I want to draw a black circle inside a table field, I currently do it with a UNI-Code character, but this causes problems when rendering on some systems and with SVG Output it is not centered(Text in Table in SVG output not completly centered ).
If there is any other better way to do this, without a Character, I would be thankful.
For reference for what it would be used for:
opened 02:09PM - 18 May 24 UTC
in #286 I suggested a way to implement Jumpers/Interconnects, this is a summery/… spinoff on the request of @kvid.
The Idea how it could look (very similar to https://github.com/wireviz/WireViz/issues/48#issuecomment-656802355):

# Black Circles ⬤
The Black circles can be implemented by adding the following to the table in the corresponding Pin/Way row:
```
<td port="p1J"><FONT FACE="Sans Not-Rotated 14" POINT-SIZE="12.0" COLOR="#0066ff">⬤</FONT></td>
```
(not very good, since the symbol can get "lost" in the process)
or
```
<td port="p1J"><FONT FACE="Sans Not-Rotated 14" POINT-SIZE="12.0" COLOR="#0066ff">⬤</FONT></td>
```
- The Port is later used to draw the vertical dashed lines.
- The Font definition is because the PNG generator's Arial font does not know the ⬤ symbol.
- The Point size change is because the Circle is clipped at the bottom, if it is not done.
- The Color is to make differentiation easier, the lines should be the same color as the corresponding ⬤
The later one(`⬤`) is better sinze it cases less problems.
Doing this will lead to the following:

# Vertical dashed lines
This is more complicated and would require a change in how the output is generated, and I do not know how to implement this in Python.
The way I was told to do it(asked about it in the [GrapghViz Forum](https://forum.graphviz.org/t/straitening-one-line-throu-a-table/2196/6) ) would require the use of gvpr and neato, with are post processors for the dot output.
I is currently not working, but I am working on it.
Some examples of my current Output:


wireviz:dev
← tobiasfalk:Jumpers
opened 02:31PM - 30 May 24 UTC
Here I started to implement Jumpers.
- https://github.com/wireviz/WireViz/iss… ues/350
Currently, only the Black circles are done and nothing else.
See ex15.png
Ps. And now even the right branch
Edit:
Ex15:

Ex16:

mark
June 18, 2024, 2:39am
2
Wonder if it would work to center with -Tsvg:cairo ? That does better font measurements
mark
June 18, 2024, 2:41am
3
I was going to say you could add a css class to cells you want a circle in, then style with css to add a circle maybe, but now I’m not sure if css class works on table cells in graphviz yet. Maybe we could make that work without much fuss.
The Problem I am having with this is that it does not work with the pip install of cairo/graphviz (on Windows at least) and that is a requierment.
mark
June 18, 2024, 6:53am
5
How are you installing graphviz from pip?
To be precise, I install WireViz and that installs graphviz · PyPI
Ok, -Tsvg:cairo
works now, do not know what I have done before, still it converts a Text to a path, what I would prefer not to do
mark
June 18, 2024, 10:53am
8
Ok. The graphviz pypi module is just Python bindings, doesn’t include a dot binary, you have to install dot (graphviz) separately.
Yes, apently I did and forged it. Still a way to draw A Black Circle inside a Table field, Without a Caracter is what I am searching for. Becaus this could be a much more reliable way than depending on fonts
Have you considered inserting an image <TD> <IMG/> </TD>
?
Not trying to sell the idea, but it would seem to simple to implement - though not necessarily easy to make work with many users.
Yes I thought about it and am working on it, but I had the hope that there would be a more elegant solution.
I don’t consider this elegant, but …
The improved pin2pin is modified again to add point-shaped nodes at the ends of marked edges.
/*******************************************************************
see https://forum.graphviz.org/t/straitening-one-line-throu-a-table/2196
input must include pos values (must be output from one of the engines w/ -Tdot)
*******************************************************************/
BEG_G{
double x1,y1,x2,y2,x3,y3,x4,y4;
string ptSize, tok[int], pt[];
int cnt, circ, i;
node_t aNode;
circ=0;
}
/********************************************************
it would be better to mark every target edge with a new attribute and test for that attribute
*********************************************************/
E{
if (hasAttr($, "addPTS") && $.addPTS!="") { // explicitly marked edges
cnt=tokens($.pos,tok," ");
$.oldpos=$.pos;
x1 = xOf(tok[0]);
y1 = yOf(tok[0]);
x4 = xOf(tok[cnt-1]);
y4 = yOf(tok[cnt-1]);
x2 = x1 + (x4-x1)/3.;
y2 = y1 + (y4-y1)/3.;
x3 = x1 + 2.*(x4-x1)/3.;
y3 = y1 + 2.*(y4-y1)/3.;
pos=sprintf("%.3f,%.3f %.3f,%.3f %.3f,%.3f %.3f,%.3f", x1,y1, x2,y2, x3,y3, x4,y4);
// now we place point nodes at the edge ends
pt[1]=tok[0];
pt[2]=tok[cnt-1];
ptSize=".13";
for (pt[i]) {
if (i==2 && pt[1]==pt[2])
continue;
aNode=node($G, "__CIRCLE__" + (string)++circ);
aNode.pos=pt[i];
aNode.shape="point";
aNode.width=ptSize;
aNode.height=ptSize;
aNode.style="filled";
aNode.fillcolor="green"; // just for fun
}
}
}
And the input looks like this:
graph {
// Graph generated by WireViz 0.3.2
// https://github.com/formatc1702/WireViz
graph [bgcolor="#FFFFFF" fontname=arial nodesep=0.33 rankdir=LR ranksep=2]
node [fillcolor="#FFFFFF" fontname=arial height=0 margin=0 shape=none style=filled width=0]
edge [fontname=arial style=bold label=" "]
X2 [label=<
<table border="0" cellspacing="0" cellpadding="0">
<tr><td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>
<td balign="left">X2</td>
</tr></table>
</td></tr>
<tr><td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>
<td balign="left">P1</td>
<td balign="left">9-pin</td>
</tr></table>
</td></tr>
<tr><td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1">
<tr>
<td port="p1l">1</td>
<td>+28VDC</td>
<td width="38" port="p1I"></td>
<td width="38" port="p1J"></td>
<td width="38" port="p1K"></td>
</tr>
<tr>
<td port="p2l">2</td>
<td>+28VDC RTN</td>
<td width="38" port="p2I"></td>
<td width="38" port="p2J"></td>
<td width="38" port="p2K"></td>
</tr>
<tr>
<td port="p3l">3</td>
<td>Token-In REF</td>
<td width="38" port="p3I"></td>
<td width="38" port="p3J"></td>
<td width="38" port="p3K"></td>
</tr>
<tr>
<td port="p4l">4</td>
<td>Token-In</td>
<td width="38" port="p4I"></td>
<td width="38" port="p4J"></td>
<td width="38" port="p4K"></td>
</tr>
<tr>
<td port="p5l">5</td>
<td>NC</td>
<td width="38" port="p5I"></td>
<td width="38" port="p5J"></td>
<td width="38" port="p5K"></td>
</tr>
<tr>
<td port="p6l">6</td>
<td>NC</td>
<td width="38" port="p6I"></td>
<td width="38" port="p6J"></td>
<td width="38" port="p6K"></td>
</tr>
<tr>
<td port="p7l">7</td>
<td>RS-485+</td>
<td width="38" port="p7I"></td>
<td width="38" port="p7J"></td>
<td width="38" port="p7K"></td>
</tr>
<tr>
<td port="p8l">8</td>
<td>RS-485-</td>
<td width="38" port="p8I"></td>
<td width="38" port="p8J"></td>
<td width="38" port="p8K"></td>
</tr>
<tr>
<td port="p9l">9</td>
<td>RS-485 Shield</td>
<td width="38" port="p9I"></td>
<td width="38" port="p9J"></td>
<td width="38" port="p9K"></td>
</tr>
</table>
</td></tr>
</table>
> fillcolor="#FFFFFF" shape=box style=filled]
edge [color="#000000:#ff0000:#000000" label=" "]
W1:w1:e -- X2:p1l:w
edge [color="#000000:#000000:#000000" label=" "]
W1:w2:e -- X2:p2l:w
edge [color="#000000:#f5f0d0:#000000" label=" "]
W1:w3:e -- X2:p7l:w
edge [color="#000000:#0066ff:#000000" label=" "]
W1:w4:e -- X2:p8l:w
edge [color="#000000:#00ff00:#000000" label=" "]
W1:w5:e -- X2:p9l:w
{ // keep edge attributes contained within subgraph
edge [color="#000000" addPTS=1 headclip=false, tailclip=false, style="dashed", constraint=false]
X2:p2I:c -- X2:p2I:c
X2:p1J:c -- X2:p5J:c
X2:p8J:c -- X2:p8J:c
X2:p9J:c -- X2:p9J:c
X2:p3K:c -- X2:p4K:c
X2:p6K:c -- X2:p9K:c [color=red] // for fun
X2:p4I:c -- X2:p5I:c
X2:p5I:c -- X2:p8I:c
}
W1 [label=<
<table border="0" cellspacing="0" cellpadding="0">
<tr><td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>
<td balign="left">W1</td>
</tr></table>
</td></tr>
<tr><td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>
<td balign="left">5x</td>
</tr></table>
</td></tr>
<tr><td>
<table border="0" cellspacing="0" cellborder="0">
<tr><td> </td></tr>
<tr>
<td><!-- 1_in --></td>
<td>
1:RD
</td>
<td>X2:1:+28VDC</td>
</tr>
<tr>
<td colspan="3" border="0" cellspacing="0" cellpadding="0" port="w1" height="6">
<table cellspacing="0" cellborder="0" border="0">
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#ff0000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
</table>
</td>
</tr>
<tr>
<td><!-- 2_in --></td>
<td>
2:BK
</td>
<td>X2:2:+28VDC RTN</td>
</tr>
<tr>
<td colspan="3" border="0" cellspacing="0" cellpadding="0" port="w2" height="6">
<table cellspacing="0" cellborder="0" border="0">
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
</table>
</td>
</tr>
<tr>
<td><!-- 3_in --></td>
<td>
3:IV
</td>
<td>X2:7:RS-485+</td>
</tr>
<tr>
<td colspan="3" border="0" cellspacing="0" cellpadding="0" port="w3" height="6">
<table cellspacing="0" cellborder="0" border="0">
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#f5f0d0" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
</table>
</td>
</tr>
<tr>
<td><!-- 4_in --></td>
<td>
4:BU
</td>
<td>X2:8:RS-485-</td>
</tr>
<tr>
<td colspan="3" border="0" cellspacing="0" cellpadding="0" port="w4" height="6">
<table cellspacing="0" cellborder="0" border="0">
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#0066ff" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
</table>
</td>
</tr>
<tr>
<td><!-- 5_in --></td>
<td>
5:GN
</td>
<td>X2:9:RS-485 Shield</td>
</tr>
<tr>
<td colspan="3" border="0" cellspacing="0" cellpadding="0" port="w5" height="6">
<table cellspacing="0" cellborder="0" border="0">
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#00ff00" border="0"></td></tr>
<tr><td colspan="3" cellpadding="0" height="2" bgcolor="#000000" border="0"></td></tr>
</table>
</td>
</tr>
<tr><td> </td></tr>
</table>
</td></tr>
</table>
> fillcolor="#FFFFFF" shape=box style=filled]
}
@ steveroush I like it, in my opinion much better than inserting Images
@steveroush Thx, modifyed it to do what I want
My end resault:
/*******************************************************************
see https://forum.graphviz.org/t/straitening-one-line-throu-a-table/2196 and https://forum.graphviz.org/t/way-of-drawing-a-black-circle-inside-a-table-field/2273/12
input must include pos values (must be output from one of the engines w/ -Tdot)#
Thanks to steveroush and FeRDNYC
*******************************************************************/
BEG_G{
double x1,y1,x2,y2,x3,y3,x4,y4;
string ptSize, tok[int], pt[];
int cnt, circ, i;
node_t aNode;
circ=0;
/***************************************
$G.bb="";
$G.nodesep="";
$G.ranksep="";
$G.splines="true";
****************************************/
}
E[straight] {
cnt=tokens($.pos,tok," ");
$.oldpos=$.pos;
x1 = xOf(tok[0]);
y1 = yOf(tok[0]);
x4 = xOf(tok[cnt-1]);
y4 = yOf(tok[cnt-1]);
x2 = x1 + (x4-x1)/3.;
y2 = y1 + (y4-y1)/3.;
x3 = x1 + 2.*(x4-x1)/3.;
y3 = y1 + 2.*(y4-y1)/3.;
pos=sprintf("%.3f,%.3f %.3f,%.3f %.3f,%.3f %.3f,%.3f", x1,y1, x2,y2, x3,y3, x4,y4);
$.label=""; // remove pesky label
$.lp=""; // remove peskier label pos
if (hasAttr($, "addPTS") && $.addPTS!="" && $.colorPTS!=""){
// now we place point nodes at the edge ends
pt[1] = tok[0];
pt[2] = tok[cnt-1];
ptSize=$.addPTS;
for (pt[i]) {
if (i==2 && pt[1]==pt[2])
continue;
aNode=node($G, "__CIRCLE__" + (string)++circ);
aNode.pos=pt[i];
aNode.shape="point";
aNode.width=ptSize;
aNode.height=ptSize;
aNode.style="filled";
aNode.fillcolor=$.colorPTS;
aNode.color=$.colorPTS;
}
}
}
smattr
June 18, 2024, 10:44pm
16
I think this has come up before and the unfortunate conclusion was this is not within our control but a decision Cairo makes on its own.
I understand that this is not in the scope of GraphViz, and it was less of a complaint that the Text is converted to a Path but more of saying that I would prefer a solution that would not do it, that I got at the end.
Also, there are situations where this Text to Path conversion is wanted/needed.
One thing is that maybe that it should be mentioned somewhere in the documentation, I at least did not see such thing in the doc.