4

I can produce the below graph with either dot language using GraphViz directly or with the PEAR package Image_GraphViz using PHP.

graphviz png image from below code

//DOT language
digraph test{
    URL="http://example.com/fish/";
    bgcolor="#BBCAF2";

    //defaults for all nodes
    node[style=filled, 
         fillcolor=white, 
         color="#8A94B4", 
         fixedsize=true, 
         fontname="sans-serif", 
         fontsize=8, 
         URL="?fish_id=\N", 
         margin="0.02,0.02"];

    //defaults for all edges
    edge[arrowsize=0.6,  
         sametail=true, 
         fontsize=8, 
         fontname="sans-serif"];

    //a few edges
    57->23[color="blue"];  42->23[color="red"];
    25->26[color="blue", label="10M"];  25->26[color="red", label="10F"];
    //etc.

    //a few nodes
    29[label="100128 AB"];
    38[label="100730 AB"];
    39[label="110208"];
    //etc.
}

Dot files can set attribute defaults for all four element types (graph, cluster, node, edge). It appears that Image_GraphViz can only set defaults for graph level attributes.

<?php
$gatts=array( //defaults for graph level attributes
    'URL'=>"http://example.com/fish/",
    'bgcolor'=>"#ff0000",
    'font'=>"sans-serif",
);

$gv=new Image_GraphViz(true,$gatts,'test',false,true);

$q_ne="SELECT parentname, parent_id, childname, child_id, parenttype, parentcount 
       FROM fish_crosses";   
$r_ne=$dbii->query($q_ne);
while($ne=$r_ne->fetch_assoc()){
    $nodeatts=array('label' => $ne['parentname'], 
                     'style'=>"filled", 
                     'fillcolor'=>'#ffffff', 
                     'fixedsize'=>true, 
                     'fontname'=>"sans-serif", 
                     'fontsize'=>8);
    if(!$ne['child_id']) {
        $gv->addNode($ne['parent_id'], $nodeatts);
        continue;
    }
    if($ne['parenttype']=='dam'){
        $ecolor= '#ff0000';
        $elabel= $ne['parentcount'].'F';
    } else {
        $ecolor= '#0000ff';
        $elabel=$ne['parentcount'].'F';
    }
    $edgeatts=array('color'=>$ecolor, 'fontname'=>'sans-serif','fontsize'=>8);
    if($ne['parentcount']) $edgeatts['label']=$elabel;

     $gv->addEdge(array($ne['parent_id']=>$ne['child_id']), $edgeatts);
    $gv->addNode($ne['parent_id'], $nodeatts);
    $gv->addNode($ne['child_id'], $nodeatts);
}

echo $gv->image('png');
?>

Does anyone know the syntax for adding default attribute values for nodes and edges to a Image_GraphViz object?

dnagirl
  • 20,196
  • 13
  • 80
  • 123

2 Answers2

0

This is just an idea, can't test it: Have you tried simply adding a node named node (or edge) and defining the attributes on that node?

Something like $gv->addNode('node', array('style'=>'filled', 'fixedsize'=>true))

marapet
  • 54,856
  • 12
  • 170
  • 184
  • Sadly, that adds a beautifully formatted extra node, named "node" and has no effect on the format of the rest of the nodes at all. – dnagirl Jun 21 '11 at 20:10
  • oh well, that would have been too easy... Please try once more with an extra space before or after *node* - I don't think the node name gets trimmed when added, and with an extra character, the [_escape](http://pear.php.net/package/Image_GraphViz/docs/latest/__filesource/fsource_Image_GraphViz__Image_GraphViz-1.3.0ImageGraphViz.php.html#a621) function may not escape it to a "safe ID". – marapet Jun 21 '11 at 20:34
  • And if that doesn't work, adding a property and modifying `parse()` doesn't look very complicated. – marapet Jun 21 '11 at 20:36
  • looks like I'll have to extend the class. Thanks for your thoughts. – dnagirl Jun 22 '11 at 13:06
0

It appears that the current Image_GraphViz package cannot handle default node/edge/cluster attributes. I've extended the class by changing these functions: _escape, _escapeArray, and parse. Here are my changes:

function _escape($input, $html = false) {
        switch (strtolower($input)) {
        //removed case 'node' and case 'edge' so they won't be quoted
        case 'graph':
        case 'digraph':
        case 'subgraph':
        case 'strict':
            return '"'.$input.'"';
        } //...


function _escapeArray($input) {
//...
        default:
            if(is_array($v)){
                $v=$this->_escapeArray($v); //added recursion to allow default node/edge/cluster attribute sets
            } else {
                $v = $this->_escape($v);
            }
            $k = $this->_escape($k);
        }
//...

function parse() {
//...
    foreach ($attr as $key => $value) {
        if(is_array($value)){
            $a=implode(',', 
            array_map(function($v,$k){ return $k . '='.$v;}, 
                array_values($value),
                array_keys($value)));
        //default format for node/edge/cluster: thing[att1="blah", att2="foo"];
            $parsedGraph .= $indent.$key.'['.$a."];\n";
        } else {
            $parsedGraph .= $indent.$key.'='.$value.";\n";
        }
    }
//...

I hope this is useful to someone.

dnagirl
  • 20,196
  • 13
  • 80
  • 123