]>
git.sthu.org Git - pgp-tools.git/blob - springgraph/springgraph
3 # springgraph v0.79, (c) 2002 Darxus@ChaosReigns.com, released under the GPL
4 # Download current version from: http://www.chaosreigns.com/code/springgraph/
6 # This program attempts to render .dot files in a fashion similar to neato,
7 # which is part of graphviz: http://www.research.att.com/sw/tools/graphviz/.
8 # I have never looked at any of the code in graphviz.
12 # cat test.dot | ./springgraph.pl -s 3 > springgraph.png
14 # The "-s 3" specifies the scale, and is optional. All of the node
15 # locations are multiplied by this. Increase the scale to eliminate
16 # node overlaps. Decrease the scale to make the graph smaller.
18 # Requirements: GD.pm (http://www.perl.com/CPAN/authors/id/L/LD/LDS/)
20 # Definition of the .dot files which springgraph renders
21 # can be found in the graphviz man pages. A copy is here:
22 # http://www.unisa.edu.au/eie/csec/graphviz/dot.1.html. Springgraph only
23 # supports the fillcolor and label node attributes, and can only handle
24 # two nodes per edge definition ("node1 -> node2", not "node1 -> node2
27 # Springgraph fully supports the .dot files generated by sig2dot
28 # (http://www.chaosreigns.com/code/sig2dot), which generates .dot files
29 # from GPG/PGP signature relationships.
31 # Thanks to the following for help with the math for the arrowheads:
32 # Mike Joseph <mj@doze.net>
33 # Walt Mankowski <waltman@pobox.com>
34 # Jeff Weisberg <jaw+plug@tcp4me.com>
36 # Yes, the placement of the freaking arrowheads was by far the hardest
37 # part of writing this program.
39 # Thanks to Hartmut Palm for cylinder translation/rotation code in
40 # VRML.pm: http://dc.gfz-potsdam.de/~palm/vrmlperl/
42 # v0.26 May 06 16:12:30 2002
43 # v0.27 May 06 18:15:38 2002 cleanup
44 # v0.44 May 06 23:56:45 2002
45 # v0.56 May 07 05:10:02 2002
46 # v0.60 May 07 23:27:29 2002 arrow heads !! (not filled in due to segfault)
47 # v0.61 May 07 2002 handle absence of beginning double-quote in fillcolor attribute
48 # v0.62 May 08 19:44:04 2002 use getopts to get scale argument
49 # v0.63 May 08 21:29:48 2002 made fillcolor optional again
50 # v0.64 May 08 22:28:40 2002 render http://www.research.att.com/sw/tools/graphviz/examples/undirected/ER.dot.txt
51 # and http://www.research.att.com/sw/tools/graphviz/examples/undirected/process.dot.txt
52 # (added support for undirected graphs ("--" links)
53 # v0.65 May 08 22:44:00 2002 render http://www.research.att.com/sw/tools/graphviz/examples/directed/fsm.dot.txt
54 # (do not attempt to draw a line from a node to itself and cause a devision by zero)
55 # v0.67 May 09 05:53:16 2002 support multiple nodes on one link line, adjusted detection of completion
56 # render http://www.research.att.com/sw/tools/graphviz/examples/directed/unix.dot.txt
57 # (support node names containing spaces)
58 # v0.68 May 09 17:29:06 2002 cleaned up link line processing a bit (removed extraneous define checks)
59 # v0.69 May 09 18:23:19 2002 render http://www.research.att.com/sw/tools/graphviz/examples/undirected/inet.dot.txt
60 # (support {} lists in link (edge) lines)
61 # v0.70 May 10 00:39:20 2002 Strip double-quotes that were getting missed to support sig2dot v0.27.
62 # v0.71 May 11 20:06:17 2002 don't draw twice, added some 3D math (but not output yet)
63 # v0.72 May 11 21:31:20 2002 3D output !!! (via -p flag)
64 # v0.73 May 11 22:34:23 2002 added labels to 3D output
65 # v0.74 May 12 02:07:29 2002 output 3D output suitable for animation
66 # v0.75 May 13 01:45:41 2002 beginnings of vrml output (-v) - colored spheres
67 # v0.76 May 13 04:30:13 2002 added connections between nodes to vrml
68 # output, thanks cylinder translation/rotation
69 # code from VRML.pm by Hartmut Palm:
70 # http://dc.gfz-potsdam.de/~palm/vrmlperl/
71 # v0.77 May 13 04:41:53 2002 made colors optional in pov and vrml output
72 # v0.78 May 13 06:31:34 2002 removed extra cylinders from vrml output
73 # v0.79 May 13 07:20:23 2002 made 2d output background transparent
74 # v0.80 Mar 19 2003 optimization patch from Marco Bodrato
75 # v0.81 Aug 20 2003 Caption stderr progress notes
172 $arrowlength = 10; # pixels
175 srand 1; #comment out this line to generate graphs differently every time
177 $pi = 3.141592653589793238462643383279502884197169399375105; # from memory
180 getopts
('s:pvhtb:l:');
197 # -p: Output as Pov-Ray
214 # -t: Make background transparent
222 # -b: Set background color
226 $opt_b =~ m/^(..)(..)(..)$/ or die "Invalid color: $opt_b";
227 @bgcolor = (hex($1), hex($2), hex($3));
229 @bgcolor = (255, 255, 255);
236 $opt_l =~ m/^(..)(..)(..)$/ or die "Invalid color: $opt_l";
237 @linecolor = (hex($1), hex($2), hex($3));
239 @linecolor = (169, 169, 169);
242 $done = $done / $scale;
244 while ($line = <STDIN
>)
247 next if ($line =~ m
#^//#);
249 # 2 = arro1, 1 = no arrow
250 if ($line =~ m
#^(.*-[>-][^\[]*)#)
253 @parts = split(/(-[->])/,$edge);
254 for $part (0 .. $#parts)
256 if (defined $parts[$part+2] and $parts[$part] ne '->' and $parts[$part] ne '--')
258 #print ":$parts[$part]:".$parts[$part+1].":".$parts[$part+2].":\n";
261 $parts[$part] =~ s/^\s*"?//;
262 $parts[$part] =~ s/"?\s*$//;
263 $parts[$part+2] =~ s/^\s*"?//;
264 $parts[$part+2] =~ s/"?\s*;?\s*$//;
265 if ($parts[$part] =~ m
#^{(.*)}$#)
268 #print STDERR "sourcesstring:$sourcesstring:\n";
269 @sources = split(/[\s*;?\s*]/,$sourcesstring);
271 $sources[0] = $parts[$part];
273 if ($parts[$part+2] =~ m
#^{(.*)}$#)
276 #print STDERR "destsstring:$destsstring:\n";
277 @dests = split(/[\s*;?\s*]/,$destsstring);
279 $dests[0] = $parts[$part+2];
281 for $source (@sources)
283 next if ($source eq "");
286 next if ($dest eq "");
287 $source =~ s/^\s*"?//;
288 $source =~ s/"?\s*$//;
290 $dest =~ s/"?\s*;?\s*$//;
291 $link{$source}{$dest} = 2 if ($parts[$part+1] eq '->');
292 $link{$source}{$dest} = 1 if ($parts[$part+1] eq '--');
293 push (@nodelist,$source,$dest);
294 #print STDERR "$source ".$parts[$part+1]." $dest\n";
302 # $source =~ s/^\W*//;
303 # $source =~ s/\W*$//;
306 # $link{$source}{$dest} = 2;
307 # push (@nodelist,$source,$dest);
308 # print STDERR "source:$source:dest:$dest:\n";
310 # if ($line =~ m#^edge# or $line =~ m#^node#)
312 # print STDERR "Skipping: $line\n";
315 if ($line =~ m
#^(\S+).*\[.*\]#)
319 if ($name eq 'node' or $name eq 'edge')
323 #print STDERR "name:$name:\n";
325 if ($line =~ m
#\[.*label=([^,\]]*).*\]#)
329 $node{$name}{'label'} = $label;
330 #print STDERR "label:$label:\n";
332 if ($line =~ m
#\[.*fillcolor="?([\d\.]+),([\d\.]+),([\d\.]+).*\]#)
337 #print STDERR "hsv:$h:$s:$v:\n";
339 ($r,$g,$b) = &hsv2rgb
($h,$s,$v);
340 $node{$name}{r
} = $r;
341 $node{$name}{g
} = $g;
342 $node{$name}{b
} = $b;
343 #print STDERR "rgb:$r:$g:$b:\n";
349 @saw{@nodelist} = ();
350 @nodelist = sort keys %saw; # remove sort if undesired
359 for $nodenum (@nodelist)
361 $node{$nodenum}{x
}=rand;# $maxx;
362 $node{$nodenum}{y
}=rand;# $maxy;
363 $node{$nodenum}{z
}=rand if $pov_or_vrml;
364 unless(defined $node{$nodenum}{'label'})
366 $node{$nodenum}{'label'} = $nodenum;
370 print STDERR
"springgraph iterating until reaches $done\n\n";
375 while($continue > $done)
379 for $nodenum (@nodelist)
381 $node{$nodenum}{oldx
} = $node{$nodenum}{x
};
382 $node{$nodenum}{oldy
} = $node{$nodenum}{y
};
383 $node{$nodenum}{oldz
} = $node{$nodenum}{z
} if $pov_or_vrml;
387 for $source (@nodelist)
390 for $dest (@nodelist)
392 next if ($source eq $dest);
393 $xdist = $node{$source}{oldx
} - $node{$dest}{oldx
};
394 $ydist = $node{$source}{oldy
} - $node{$dest}{oldy
};
395 $dist = $xdist*$xdist + $ydist*$ydist;
398 $zdist = $node{$source}{oldz
} - $node{$dest}{oldz
};
399 $dist += $zdist*$zdist;
401 # $distance = sqrt($dist);
402 $percent = $push / $dist;
403 if ($link{$source}{$dest})
407 if ($link{$dest}{$source})
412 $xmove -= $xdist * $percent;
413 $ymove -= $ydist * $percent;
414 $zmove -= $zdist * $percent if $pov_or_vrml;
416 # $pullmove = $pull * $dist;
417 # $pushmove = $push / $dist;
418 # print STDERR "dist: $dist, pull: $pullmove, push: $pushmove\n";
419 # print STDERR "$source to ${dest}, Dist: $dist Want: $wantdist (${percent}x)\n";
420 # print STDERR "is: $node[$source]{oldx} $node[$source]{oldy} $xdist $ydist, want: $wantxdist $wantydist ($newdist2)\n";
423 $xmove = $xmove / $movecount;
424 $ymove = $ymove / $movecount;
425 $zmove = $zmove / $movecount if $pov_or_vrml;
426 $node{$source}{x
} -= $xmove;
427 $node{$source}{y
} -= $ymove;
428 $node{$source}{z
} -= $zmove if $pov_or_vrml;
429 if ($xmove > $continue)
433 if ($ymove > $continue)
437 if (($pov_or_vrml) and $zmove > $continue)
442 #print STDERR "$iter\n";
446 open (XV
,"| xv -wait 1 -");
447 #open (XV,"| xloadimage -delay 1 stdin");
454 print STDERR
"$continue\n";
457 print STDERR
"Iterations: $iter\n";
458 for $source (@nodelist)
460 for $color ('r', 'g', 'b')
462 $node{$source}{$color} = 255 unless (defined $node{$source}{$color});
478 for $nodenum (@nodelist)
480 if (!(defined $maxx) or (($node{$nodenum}{x
} + (length($node{$nodenum}{'label'}) * 8 + 16)/2) > $maxx + (length($node{$nodenum}{'label'}) * 8 + 16)/2))
482 $maxx = $node{$nodenum}{x
};# + (length($node{$nodenum}{'label'}) * 8 + 16)/2/2
483 $maxxlength = (length($node{$nodenum}{'label'}) * 8 + 16)/2;
485 if (!(defined $minx) or (($node{$nodenum}{x
} - (length($node{$nodenum}{'label'}) * 8 + 16)/2) < $minx - (length($node{$nodenum}{'label'}) * 8 + 16)/2))
487 $minx = $node{$nodenum}{x
};# - (length($node{$nodenum}{'label'}) * 8 + 16)/2/2
488 $minxlength = (length($node{$nodenum}{'label'}) * 8 + 16)/2;
491 $maxy = $node{$nodenum}{y
} if (!(defined $maxy) or $node{$nodenum}{y
} > $maxy);
492 $miny = $node{$nodenum}{y
} if (!(defined $miny) or $node{$nodenum}{y
} < $miny);
494 for $nodenum (@nodelist)
496 #$node{$nodenum}{x} = ($node{$nodenum}{x} - $minx) * $scale + $margin;
497 $node{$nodenum}{x
} = ($node{$nodenum}{x
} - $minx) * $scale + $minxlength -1 ;# + $margin;
498 $node{$nodenum}{y
} = ($node{$nodenum}{y
} - $miny) * $scale + $nodesize/2 - 1;
500 $maxx = ($maxx - $minx) * $scale + $minxlength + $maxxlength;# + $margin*2;
501 $maxy = ($maxy - $miny) * $scale + $nodesize/2*2;
502 $im = new GD
::Image
($maxx,$maxy);
503 $bgcol = $im->colorAllocate(@bgcolor);
504 $im->transparent($bgcol) if $trans; # make transparent
505 $blue = $im->colorAllocate(0,0,255);
506 $powderblue = $im->colorAllocate(176,224,230);
507 $black = $im->colorAllocate(0,0,0);
508 $linecol = $im->colorAllocate(@linecolor);
510 for $source (@nodelist)
512 #print STDERR "node: $source $node[$source]{x},$node[$source]{y}\n";
513 for $dest (@nodelist)
515 if (defined $link{$source}{$dest} and $link{$source}{$dest} == 2 and $source ne $dest)
517 $dist = sqrt( abs($node{$source}{x
}-$node{$dest}{x
})**2 + abs($node{$source}{y
}-$node{$dest}{y
})**2 );
518 $xdist = $node{$source}{x
} - $node{$dest}{x
};
519 $ydist = $node{$source}{y
} - $node{$dest}{y
};
521 $angle = &acos
($xdist/$dist);
522 #$angle = atan2($ydist,$xdist);
523 #$angle += $pi if $ydist < 0;
524 #$dist = abs(cos($angle))*(length($node{$dest}{'label'}) * 8 + 16)/2 + abs(sin($angle))*$nodesize/2;
525 $width = (length($node{$dest}{'label'}) * 8 + 16)/2;
526 $height = $nodesize/2;
527 $dist = sqrt( ($height**2 * $width**2) / ( ($height**2 * (cos($angle)**2) ) + ($width**2 * (sin($angle)**2) ) ));
529 $xmove = cos($angle)*$dist;
530 $ymove = sin($angle)*$dist;
531 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
532 $point[0]{x
} = $xmove;
533 $point[0]{y
} = $ymove;
535 $xmove = cos($angle)*($dist+$arrowlength-3);
536 $ymove = sin($angle)*($dist+$arrowlength-3);
537 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
538 $point[3]{x
} = $xmove;
539 $point[3]{y
} = $ymove;
541 #$angle = $angle + $arrowwidth/2;
543 $xmove = $xmove + cos($angle)*$dist;
544 $ymove = $ymove + sin($angle)*$dist;
545 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
547 $angle = $angle + $twopi/4;
548 $dist = $arrowwidth/2;
549 $xmove = $xmove + cos($angle)*$dist;
550 $ymove = $ymove + sin($angle)*$dist;
551 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
552 $point[1]{x
} = $xmove;
553 $point[1]{y
} = $ymove;
555 $angle = $angle + $twopi/2;
557 $xmove = $xmove + cos($angle)*$dist;
558 $ymove = $ymove + sin($angle)*$dist;
559 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
560 $point[2]{x
} = $xmove;
561 $point[2]{y
} = $ymove;
565 $point[$num]{y
} = - $point[$num]{y
} if $ydist < 0;
568 $im->line($node{$dest}{x
}+$point[0]{x
},$node{$dest}{y
}+$point[0]{y
},$node{$dest}{x
}+$point[1]{x
},$node{$dest}{y
}+$point[1]{y
},$linecol);
569 $im->line($node{$dest}{x
}+$point[1]{x
},$node{$dest}{y
}+$point[1]{y
},$node{$dest}{x
}+$point[2]{x
},$node{$dest}{y
}+$point[2]{y
},$linecol);
570 $im->line($node{$dest}{x
}+$point[2]{x
},$node{$dest}{y
}+$point[2]{y
},$node{$dest}{x
}+$point[0]{x
},$node{$dest}{y
}+$point[0]{y
},$linecol);
571 # $xmove = int($node{$dest}{x}+$point[3]{x});
572 # $ymove = int($node{$dest}{y}+$point[3]{y});
573 # $im->fillToBorder($xmove,$ymove,$linecol,$powderblue);
574 #$im->fillToBorder($node{$dest}{x}+$point[3]{x},$node{$dest}{y}+$point[3]{y},$linecol,$linecol);
575 #$im->line($point[1]{x},$point[1]{y},$point[2]{x},$point[2]{y},$linecol);
576 #$im->line($point[2]{x},$point[2]{y},$point[0]{x},$point[0]{y},$linecol);
577 #$im->fillToBorder($point[3]{x},$point[3]{y},$linecol,$linecol);
578 #$im->arc($point[3]{x},$point[3]{y},10,10,0,360,$black);
580 # $im->arc($point[0]{x},$point[0]{y},20,20,0,360,$black);
581 # $im->arc($point[1]{x},$point[1]{y},20,20,0,360,$black);
582 # $im->arc($point[2]{x},$point[2]{y},20,20,0,360,$black);
583 #$im->arc($node{$dest}{x}+$xmove,$node{$dest}{y}+$ymove,20,20,0,360,$black);
587 for $source (@nodelist)
589 for $dest (@nodelist)
591 if ($link{$source}{$dest})
593 $im->line($node{$source}{x
},$node{$source}{y
},$node{$dest}{x
},$node{$dest}{y
},$linecol);
598 for $source (@nodelist)
600 $im->arc($node{$source}{x
},$node{$source}{y
},(length($node{$source}{'label'}) * 8 + 16),$nodesize,0,360,$black);
601 #$im->arc($node{$source}{x},$node{$source}{y},$nodesize,$nodesize,0,360,$black);
602 if (defined $node{$source}{r
} and defined $node{$source}{g
} and defined $node{$source}{b
})
604 $color = $im->colorResolve($node{$source}{r
},$node{$source}{g
},$node{$source}{b
});
609 $im->fillToBorder($node{$source}{x
},$node{$source}{y
},$black,$color);
611 for $source (@nodelist)
613 $im->string(gdLargeFont
,$node{$source}{x
} - (length($node{$source}{'label'}) * 8 / 2) ,$node{$source}{y
}-8,$node{$source}{'label'},$black);
623 print'// Generated by springgraph, by Darxus@ChaosReigns.com:
624 // http://www.ChaosReigns.com/code/springgraph/
626 #include "colors.inc"
627 #include "shapes.inc"
628 #include "textures.inc"
630 #include "stones.inc"
631 light_source {<0, 400, -500> color White rotate <0, 360*clock, 0>}
632 light_source {<400, 0, -500> color White rotate <0, 360*clock, 0>}
635 for $source (@nodelist)
637 $node{$source}{x
} = $node{$source}{x
} * $scale;
638 $node{$source}{y
} = $node{$source}{y
} * $scale;
639 $node{$source}{z
} = $node{$source}{z
} * $scale;
640 $node{$source}{r
} = $node{$source}{r
} / 256;
641 $node{$source}{g
} = $node{$source}{g
} / 256;
642 $node{$source}{b
} = $node{$source}{b
} / 256;
644 for $source (@nodelist)
646 print "sphere { <$node{$source}{x},$node{$source}{y},$node{$source}{z}>, 15 pigment {color rgb<$node{$source}{r},$node{$source}{g},$node{$source}{b}>}}\n";
647 print "text { ttf \"crystal.ttf\", \"$node{$source}{'label'}\", 0.5, 0 translate 2*x rotate <0, 360*clock, 0> translate -0.375*y scale 10 translate <$node{$source}{x},$node{$source}{y},$node{$source}{z}> pigment {color rgb<$node{$source}{r},$node{$source}{g},$node{$source}{b}>}}\n";
648 #print "text { ttf \"crystal.ttf\", \"$node{$source}{'label'}\", 0.5, 0 translate -".scalar(length($node{$source}{'label'})*0.25)."*x scale 10 translate <$node{$source}{x},$node{$source}{y},$node{$source}{z}> pigment {color rgb<$node{$source}{r},$node{$source}{g},$node{$source}{b}>}}\n";
649 for $dest (@nodelist)
651 if ($link{$source}{$dest})
653 print "cylinder {<$node{$source}{x},$node{$source}{y},$node{$source}{z}>,<$node{$dest}{x},$node{$dest}{y},$node{$dest}{z}> 0.5 pigment {color rgb<0.5,0.5,0.5>}}\n";
658 location <0, 0, -500>
662 rotate <0, 360*clock, 0>
671 my ($t,$r,$length,$color);
672 print'#VRML V2.0 utf8
675 info ["Generated by springgraph, by Darxus@ChaosReigns.com: http://www.ChaosReigns.com/code/springgraph/"]
680 for $source (@nodelist)
682 $node{$source}{x
} = $node{$source}{x
} * $scale;
683 $node{$source}{y
} = $node{$source}{y
} * $scale;
684 $node{$source}{z
} = $node{$source}{z
} * $scale;
685 for $color ('r', 'g', 'b')
687 if (defined $node{$source}{$color})
689 $node{$source}{$color} = $node{$source}{$color} / 256;
693 for $source (@nodelist)
697 translation $node{$source}{x} $node{$source}{y} $node{$source}{z}
700 appearance Appearance {
702 diffuseColor $node{$source}{r} $node{$source}{g} $node{$source}{b}
705 geometry Sphere{radius 15}
711 #print "sphere { <$node{$source}{x},$node{$source}{y},$node{$source}{z}>, 15 pigment {color rgb<$node{$source}{r},$node{$source}{g},$node{$source}{b}>}}\n";
712 #print "text { ttf \"crystal.ttf\", \"$node{$source}{'label'}\", 0.5, 0 translate 2*x rotate <0, 360*clock, 0> translate -0.375*y scale 10 translate <$node{$source}{x},$node{$source}{y},$node{$source}{z}> pigment {color rgb<$node{$source}{r},$node{$source}{g},$node{$source}{b}>}}\n";
713 #print "text { ttf \"crystal.ttf\", \"$node{$source}{'label'}\", 0.5, 0 translate -".scalar(length($node{$source}{'label'})*0.25)."*x scale 10 translate <$node{$source}{x},$node{$source}{y},$node{$source}{z}> pigment {color rgb<$node{$source}{r},$node{$source}{g},$node{$source}{b}>}}\n";
714 for $dest (@nodelist)
716 if ($link{$source}{$dest})
718 ($t,$r,$length) = &cylinder
($node{$source}{x
},$node{$source}{y
},$node{$source}{z
},$node{$dest}{x
},$node{$dest}{y
},$node{$dest}{z
});
725 appearance Appearance {
727 diffuseColor 0.5 0.5 0.5
747 # location <0, 0, -500>
749 # right <4/3, 0.0, 0>
751 # rotate <0, 360*clock, 0>
762 #from http://faqchest.dynhost.com/prgm/perlu-l/perl-01/perl-0101/perl-010100/perl01010410_17820.html
764 # Given an h/s/v array, return an r/g/b array.
765 # The r/g/b values will each be between 0 and 255.
766 # The h value will be between 0 and 360, and
767 # the s and v values will be between 0 and 1.
774 # limit this to h values between 0 and 360 and s/v values
777 unless (defined($h) && defined($s) && defined($v) &&
778 $h >= 0 && $s >= 0 && $v >= 0 &&
779 $h <= 360 && $s <= 1 && $v <= 1) {
780 return (undef, undef, undef);
787 # 0.003 is less than 1/255; use this to make the floating point
788 # approximation of zero, since the resulting rgb values will
789 # normally be used as integers between 0 and 255. Feel free to
790 # change this approximation of zero to something else, if this
798 my $sector = int($h);
799 my $fraction = $h - $sector;
801 my $p = $v * (1 - $s);
802 my $q = $v * (1 - ($s * $fraction));
803 my $t = $v * (1 - ($s * (1 - $fraction)));
810 elsif ($sector == 1) {
815 elsif ($sector == 2) {
820 elsif ($sector == 3) {
825 elsif ($sector == 4) {
837 # Convert the r/g/b values to all be between 0 and 255; use the
838 # ol' 0.003 approximation again, with the same comment as above.
840 $r = ($r < 0.003 ?
0.0 : $r * 255);
841 $g = ($g < 0.003 ?
0.0 : $g * 255);
842 $b = ($b < 0.003 ?
0.0 : $b * 255);
848 sub acos
{ atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }
852 my ($x1,$y1,$z1,$x2,$y2,$z2) = @_;
853 my ($t, $r, $length, $rx, $ry, $rz, $dist);
866 $length = sqrt($dx*$dx + $dy*$dy + $dz*$dz);
870 $dist = sqrt(abs($rx)**2 + abs($ry)**2);
871 $dist = sqrt(abs($rz)**2 + abs($dist)**2);
875 $t = ($x1-($dx/2))." ".($y1-($dy/2))." ".($z1-($dz/2));
876 $r = "$rx $ry $rz $pi";
879 return ($t,$r,$length);
884 springgraph - Render a .dot file into a graphic, taking that dot file
885 on standard in and delivering a PNG on standard out.
888 springgraph [-p] [-v] [-s scale] [-t] [-b color] [-l color] [-h] \\
889 < example.dot > example.png
891 -p Create a file that can be rendered with POV-Ray
892 -v Create a VRML file
893 -s This option specifies the scale. All of the node locations
894 are multiplied by this. Increase the scale to eliminate node
895 overlaps. Decrease the scale to make the graph smaller.
896 -t Make the background of the resulting image transpaent.
897 -b set background color of image, specify it in the form RRGGBB,
898 in hex digits, e.g. FFFFFF is white, 000000 is black, FF0000
900 -l set the line color, same format as the background color