]>
git.sthu.org Git - pgp-tools.git/blob - springgraph/springgraph
4a179882ec36c2af45a3c95950325dd84140558a
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
173 $arrowlength = 10; # pixels
176 srand 1; #comment out this line to generate graphs differently every time
178 $pi = 3.141592653589793238462643383279502884197169399375105; # from memory
181 getopts
('s:pvhtb:l:');
191 # -p: Output as Pov-Ray
213 # -t: Make background transparent
221 # -b: Set background color
225 $opt_b =~ m/^(..)(..)(..)$/ or die "Invalid color: $opt_b";
226 @bgcolor = (hex($1), hex($2), hex($3));
228 @bgcolor = (255, 255, 255);
235 $opt_l =~ m/^(..)(..)(..)$/ or die "Invalid color: $opt_l";
236 @linecolor = (hex($1), hex($2), hex($3));
238 @linecolor = (169, 169, 169);
241 $done = $done / $scale;
243 while ($line = <STDIN
>)
246 next if ($line =~ m
#^//#);
248 # 2 = arro1, 1 = no arrow
249 if ($line =~ m
#^(.*-[>-][^\[]*)#)
252 @parts = split(/(-[->])/,$edge);
253 for $part (0 .. $#parts)
255 if (defined $parts[$part+2] and $parts[$part] ne '->' and $parts[$part] ne '--')
257 #print ":$parts[$part]:".$parts[$part+1].":".$parts[$part+2].":\n";
260 $parts[$part] =~ s/^\s*"?//;
261 $parts[$part] =~ s/"?\s*$//;
262 $parts[$part+2] =~ s/^\s*"?//;
263 $parts[$part+2] =~ s/"?\s*;?\s*$//;
264 if ($parts[$part] =~ m
#^{(.*)}$#)
267 #print STDERR "sourcesstring:$sourcesstring:\n";
268 @sources = split(/[\s*;?\s*]/,$sourcesstring);
270 $sources[0] = $parts[$part];
272 if ($parts[$part+2] =~ m
#^{(.*)}$#)
275 #print STDERR "destsstring:$destsstring:\n";
276 @dests = split(/[\s*;?\s*]/,$destsstring);
278 $dests[0] = $parts[$part+2];
280 for $source (@sources)
282 next if ($source eq "");
285 next if ($dest eq "");
286 $source =~ s/^\s*"?//;
287 $source =~ s/"?\s*$//;
289 $dest =~ s/"?\s*;?\s*$//;
290 $link{$source}{$dest} = 2 if ($parts[$part+1] eq '->');
291 $link{$source}{$dest} = 1 if ($parts[$part+1] eq '--');
292 push (@nodelist,$source,$dest);
293 #print STDERR "$source ".$parts[$part+1]." $dest\n";
301 # $source =~ s/^\W*//;
302 # $source =~ s/\W*$//;
305 # $link{$source}{$dest} = 2;
306 # push (@nodelist,$source,$dest);
307 # print STDERR "source:$source:dest:$dest:\n";
309 # if ($line =~ m#^edge# or $line =~ m#^node#)
311 # print STDERR "Skipping: $line\n";
314 if ($line =~ m
#^(\S+).*\[.*\]#)
318 if ($name eq 'node' or $name eq 'edge')
322 #print STDERR "name:$name:\n";
324 if ($line =~ m
#\[.*label=([^,\]]*).*\]#)
328 $node{$name}{'label'} = $label;
329 #print STDERR "label:$label:\n";
331 if ($line =~ m
#\[.*fillcolor="?([\d\.]+),([\d\.]+),([\d\.]+).*\]#)
336 #print STDERR "hsv:$h:$s:$v:\n";
338 ($r,$g,$b) = &hsv2rgb
($h,$s,$v);
339 $node{$name}{r
} = $r;
340 $node{$name}{g
} = $g;
341 $node{$name}{b
} = $b;
342 #print STDERR "rgb:$r:$g:$b:\n";
348 @saw{@nodelist} = ();
349 @nodelist = sort keys %saw; # remove sort if undesired
358 for $nodenum (@nodelist)
360 $node{$nodenum}{x
}=rand;# $maxx;
361 $node{$nodenum}{y
}=rand;# $maxy;
362 $node{$nodenum}{z
}=rand if $pov_or_vrml;
363 unless(defined $node{$nodenum}{'label'})
365 $node{$nodenum}{'label'} = $nodenum;
369 print STDERR
"springgraph iterating until reaches $done\n\n";
374 while($continue > $done)
378 for $nodenum (@nodelist)
380 $node{$nodenum}{oldx
} = $node{$nodenum}{x
};
381 $node{$nodenum}{oldy
} = $node{$nodenum}{y
};
382 $node{$nodenum}{oldz
} = $node{$nodenum}{z
} if $pov_or_vrml;
386 for $source (@nodelist)
389 for $dest (@nodelist)
391 next if ($source eq $dest);
392 $xdist = $node{$source}{oldx
} - $node{$dest}{oldx
};
393 $ydist = $node{$source}{oldy
} - $node{$dest}{oldy
};
394 $dist = $xdist*$xdist + $ydist*$ydist;
397 $zdist = $node{$source}{oldz
} - $node{$dest}{oldz
};
398 $dist += $zdist*$zdist;
400 # $distance = sqrt($dist);
401 $percent = $push / $dist;
402 if ($link{$source}{$dest})
406 if ($link{$dest}{$source})
411 $xmove -= $xdist * $percent;
412 $ymove -= $ydist * $percent;
413 $zmove -= $zdist * $percent if $pov_or_vrml;
415 # $pullmove = $pull * $dist;
416 # $pushmove = $push / $dist;
417 # print STDERR "dist: $dist, pull: $pullmove, push: $pushmove\n";
418 # print STDERR "$source to ${dest}, Dist: $dist Want: $wantdist (${percent}x)\n";
419 # print STDERR "is: $node[$source]{oldx} $node[$source]{oldy} $xdist $ydist, want: $wantxdist $wantydist ($newdist2)\n";
422 $xmove = $xmove / $movecount;
423 $ymove = $ymove / $movecount;
424 $zmove = $zmove / $movecount if $pov_or_vrml;
425 $node{$source}{x
} -= $xmove;
426 $node{$source}{y
} -= $ymove;
427 $node{$source}{z
} -= $zmove if $pov_or_vrml;
428 if ($xmove > $continue)
432 if ($ymove > $continue)
436 if (($pov_or_vrml) and $zmove > $continue)
441 #print STDERR "$iter\n";
445 open (XV
,"| xv -wait 1 -");
446 #open (XV,"| xloadimage -delay 1 stdin");
453 print STDERR
"$continue\n";
456 print STDERR
"Iterations: $iter\n";
457 for $source (@nodelist)
459 for $color ('r', 'g', 'b')
461 $node{$source}{$color} = 255 unless (defined $node{$source}{$color});
477 for $nodenum (@nodelist)
479 if (!(defined $maxx) or (($node{$nodenum}{x
} + (length($node{$nodenum}{'label'}) * 8 + 16)/2) > $maxx + (length($node{$nodenum}{'label'}) * 8 + 16)/2))
481 $maxx = $node{$nodenum}{x
};# + (length($node{$nodenum}{'label'}) * 8 + 16)/2/2
482 $maxxlength = (length($node{$nodenum}{'label'}) * 8 + 16)/2;
484 if (!(defined $minx) or (($node{$nodenum}{x
} - (length($node{$nodenum}{'label'}) * 8 + 16)/2) < $minx - (length($node{$nodenum}{'label'}) * 8 + 16)/2))
486 $minx = $node{$nodenum}{x
};# - (length($node{$nodenum}{'label'}) * 8 + 16)/2/2
487 $minxlength = (length($node{$nodenum}{'label'}) * 8 + 16)/2;
490 $maxy = $node{$nodenum}{y
} if (!(defined $maxy) or $node{$nodenum}{y
} > $maxy);
491 $miny = $node{$nodenum}{y
} if (!(defined $miny) or $node{$nodenum}{y
} < $miny);
493 for $nodenum (@nodelist)
495 #$node{$nodenum}{x} = ($node{$nodenum}{x} - $minx) * $scale + $margin;
496 $node{$nodenum}{x
} = ($node{$nodenum}{x
} - $minx) * $scale + $minxlength -1 ;# + $margin;
497 $node{$nodenum}{y
} = ($node{$nodenum}{y
} - $miny) * $scale + $nodesize/2 - 1;
499 $maxx = ($maxx - $minx) * $scale + $minxlength + $maxxlength;# + $margin*2;
500 $maxy = ($maxy - $miny) * $scale + $nodesize/2*2;
501 $im = new GD
::Image
($maxx,$maxy);
502 $bgcol = $im->colorAllocate(@bgcolor);
503 $im->transparent($bgcol) if $trans; # make transparent
504 $blue = $im->colorAllocate(0,0,255);
505 $powderblue = $im->colorAllocate(176,224,230);
506 $black = $im->colorAllocate(0,0,0);
507 $linecol = $im->colorAllocate(@linecolor);
509 for $source (@nodelist)
511 #print STDERR "node: $source $node[$source]{x},$node[$source]{y}\n";
512 for $dest (@nodelist)
514 if (defined $link{$source}{$dest} and $link{$source}{$dest} == 2 and $source ne $dest)
516 $dist = sqrt( abs($node{$source}{x
}-$node{$dest}{x
})**2 + abs($node{$source}{y
}-$node{$dest}{y
})**2 );
517 $xdist = $node{$source}{x
} - $node{$dest}{x
};
518 $ydist = $node{$source}{y
} - $node{$dest}{y
};
520 $angle = &acos
($xdist/$dist);
521 #$angle = atan2($ydist,$xdist);
522 #$angle += $pi if $ydist < 0;
523 #$dist = abs(cos($angle))*(length($node{$dest}{'label'}) * 8 + 16)/2 + abs(sin($angle))*$nodesize/2;
524 $width = (length($node{$dest}{'label'}) * 8 + 16)/2;
525 $height = $nodesize/2;
526 $dist = sqrt( ($height**2 * $width**2) / ( ($height**2 * (cos($angle)**2) ) + ($width**2 * (sin($angle)**2) ) ));
528 $xmove = cos($angle)*$dist;
529 $ymove = sin($angle)*$dist;
530 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
531 $point[0]{x
} = $xmove;
532 $point[0]{y
} = $ymove;
534 $xmove = cos($angle)*($dist+$arrowlength-3);
535 $ymove = sin($angle)*($dist+$arrowlength-3);
536 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
537 $point[3]{x
} = $xmove;
538 $point[3]{y
} = $ymove;
540 #$angle = $angle + $arrowwidth/2;
542 $xmove = $xmove + cos($angle)*$dist;
543 $ymove = $ymove + sin($angle)*$dist;
544 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
546 $angle = $angle + $twopi/4;
547 $dist = $arrowwidth/2;
548 $xmove = $xmove + cos($angle)*$dist;
549 $ymove = $ymove + sin($angle)*$dist;
550 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
551 $point[1]{x
} = $xmove;
552 $point[1]{y
} = $ymove;
554 $angle = $angle + $twopi/2;
556 $xmove = $xmove + cos($angle)*$dist;
557 $ymove = $ymove + sin($angle)*$dist;
558 #$ymove = -$ymove if $ydist < 0; # the part mj omitted
559 $point[2]{x
} = $xmove;
560 $point[2]{y
} = $ymove;
564 $point[$num]{y
} = - $point[$num]{y
} if $ydist < 0;
567 $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);
568 $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);
569 $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);
570 # $xmove = int($node{$dest}{x}+$point[3]{x});
571 # $ymove = int($node{$dest}{y}+$point[3]{y});
572 # $im->fillToBorder($xmove,$ymove,$linecol,$powderblue);
573 #$im->fillToBorder($node{$dest}{x}+$point[3]{x},$node{$dest}{y}+$point[3]{y},$linecol,$linecol);
574 #$im->line($point[1]{x},$point[1]{y},$point[2]{x},$point[2]{y},$linecol);
575 #$im->line($point[2]{x},$point[2]{y},$point[0]{x},$point[0]{y},$linecol);
576 #$im->fillToBorder($point[3]{x},$point[3]{y},$linecol,$linecol);
577 #$im->arc($point[3]{x},$point[3]{y},10,10,0,360,$black);
579 # $im->arc($point[0]{x},$point[0]{y},20,20,0,360,$black);
580 # $im->arc($point[1]{x},$point[1]{y},20,20,0,360,$black);
581 # $im->arc($point[2]{x},$point[2]{y},20,20,0,360,$black);
582 #$im->arc($node{$dest}{x}+$xmove,$node{$dest}{y}+$ymove,20,20,0,360,$black);
586 for $source (@nodelist)
588 for $dest (@nodelist)
590 if ($link{$source}{$dest})
592 $im->line($node{$source}{x
},$node{$source}{y
},$node{$dest}{x
},$node{$dest}{y
},$linecol);
597 for $source (@nodelist)
599 $im->arc($node{$source}{x
},$node{$source}{y
},(length($node{$source}{'label'}) * 8 + 16),$nodesize,0,360,$black);
600 #$im->arc($node{$source}{x},$node{$source}{y},$nodesize,$nodesize,0,360,$black);
601 if (defined $node{$source}{r
} and defined $node{$source}{g
} and defined $node{$source}{b
})
603 $color = $im->colorResolve($node{$source}{r
},$node{$source}{g
},$node{$source}{b
});
608 $im->fillToBorder($node{$source}{x
},$node{$source}{y
},$black,$color);
610 for $source (@nodelist)
612 $im->string(gdLargeFont
,$node{$source}{x
} - (length($node{$source}{'label'}) * 8 / 2) ,$node{$source}{y
}-8,$node{$source}{'label'},$black);
622 print'// Generated by springgraph, by Darxus@ChaosReigns.com:
623 // http://www.ChaosReigns.com/code/springgraph/
625 #include "colors.inc"
626 #include "shapes.inc"
627 #include "textures.inc"
629 #include "stones.inc"
630 light_source {<0, 400, -500> color White rotate <0, 360*clock, 0>}
631 light_source {<400, 0, -500> color White rotate <0, 360*clock, 0>}
634 for $source (@nodelist)
636 $node{$source}{x
} = $node{$source}{x
} * $scale;
637 $node{$source}{y
} = $node{$source}{y
} * $scale;
638 $node{$source}{z
} = $node{$source}{z
} * $scale;
639 $node{$source}{r
} = $node{$source}{r
} / 256;
640 $node{$source}{g
} = $node{$source}{g
} / 256;
641 $node{$source}{b
} = $node{$source}{b
} / 256;
643 for $source (@nodelist)
645 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";
646 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";
647 #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";
648 for $dest (@nodelist)
650 if ($link{$source}{$dest})
652 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";
657 location <0, 0, -500>
661 rotate <0, 360*clock, 0>
670 my ($t,$r,$length,$color);
671 print'#VRML V2.0 utf8
674 info ["Generated by springgraph, by Darxus@ChaosReigns.com: http://www.ChaosReigns.com/code/springgraph/"]
679 for $source (@nodelist)
681 $node{$source}{x
} = $node{$source}{x
} * $scale;
682 $node{$source}{y
} = $node{$source}{y
} * $scale;
683 $node{$source}{z
} = $node{$source}{z
} * $scale;
684 for $color ('r', 'g', 'b')
686 if (defined $node{$source}{$color})
688 $node{$source}{$color} = $node{$source}{$color} / 256;
692 for $source (@nodelist)
696 translation $node{$source}{x} $node{$source}{y} $node{$source}{z}
699 appearance Appearance {
701 diffuseColor $node{$source}{r} $node{$source}{g} $node{$source}{b}
704 geometry Sphere{radius 15}
710 #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";
711 #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";
712 #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";
713 for $dest (@nodelist)
715 if ($link{$source}{$dest})
717 ($t,$r,$length) = &cylinder
($node{$source}{x
},$node{$source}{y
},$node{$source}{z
},$node{$dest}{x
},$node{$dest}{y
},$node{$dest}{z
});
724 appearance Appearance {
726 diffuseColor 0.5 0.5 0.5
746 # location <0, 0, -500>
748 # right <4/3, 0.0, 0>
750 # rotate <0, 360*clock, 0>
761 #from http://faqchest.dynhost.com/prgm/perlu-l/perl-01/perl-0101/perl-010100/perl01010410_17820.html
763 # Given an h/s/v array, return an r/g/b array.
764 # The r/g/b values will each be between 0 and 255.
765 # The h value will be between 0 and 360, and
766 # the s and v values will be between 0 and 1.
773 # limit this to h values between 0 and 360 and s/v values
776 unless (defined($h) && defined($s) && defined($v) &&
777 $h >= 0 && $s >= 0 && $v >= 0 &&
778 $h <= 360 && $s <= 1 && $v <= 1) {
779 return (undef, undef, undef);
786 # 0.003 is less than 1/255; use this to make the floating point
787 # approximation of zero, since the resulting rgb values will
788 # normally be used as integers between 0 and 255. Feel free to
789 # change this approximation of zero to something else, if this
797 my $sector = int($h);
798 my $fraction = $h - $sector;
800 my $p = $v * (1 - $s);
801 my $q = $v * (1 - ($s * $fraction));
802 my $t = $v * (1 - ($s * (1 - $fraction)));
809 elsif ($sector == 1) {
814 elsif ($sector == 2) {
819 elsif ($sector == 3) {
824 elsif ($sector == 4) {
836 # Convert the r/g/b values to all be between 0 and 255; use the
837 # ol' 0.003 approximation again, with the same comment as above.
839 $r = ($r < 0.003 ?
0.0 : $r * 255);
840 $g = ($g < 0.003 ?
0.0 : $g * 255);
841 $b = ($b < 0.003 ?
0.0 : $b * 255);
847 sub acos
{ atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }
851 my ($x1,$y1,$z1,$x2,$y2,$z2) = @_;
852 my ($t, $r, $length, $rx, $ry, $rz, $dist);
865 $length = sqrt($dx*$dx + $dy*$dy + $dz*$dz);
869 $dist = sqrt(abs($rx)**2 + abs($ry)**2);
870 $dist = sqrt(abs($rz)**2 + abs($dist)**2);
874 $t = ($x1-($dx/2))." ".($y1-($dy/2))." ".($z1-($dz/2));
875 $r = "$rx $ry $rz $pi";
878 return ($t,$r,$length);
883 springgraph - Render a .dot file into a graphic
885 Usage: springgraph [-p] [-v] [-s scale] [-t] [-b color] [-l color] [-h]
887 -p Create a file that can be rendered with POV-Ray
888 -v Create a VRML file
889 -s This option specifies the scale. All of the node locations
890 are multiplied by this. Increase the scale to eliminate node
891 overlaps. Decrease the scale to make the graph smaller.
892 -t Make the background of the resulting image transpaent.
893 -b set background color of image, specify it in the form RRGGBB,
894 in hex digits, e.g. FFFFFF is white, 000000 is black, FF0000
896 -l set the line color, same format as the background color