#!/usr/bin/perl -w use strict; # This takes two 2-dimensional points (A and B) # and a width, and returns 4 points that are the # counter-clockwise perimeter of a "thick line" # (box) of the specified width around the line. sub line2box { my $w= pop @_; die 'Usage: line2box($ax,$ay,$bx,$by,$width)' if $w <= 0 || 4 != @_; # We just keep our 4 coordinates in a single array # so we don't have to repeat ourselves much below. $w /= 2; # Length of offset vector is $width/2 my @d; # Differences between X and Y coord.s my $l= 0; for( 0, 1 ) { my $d= $_[$_] - $_[2+$_]; $l += $d*$d; push @d, $d; } # Now $l is length**2, so we want to scale our # perpendicular vectors by $width / $length so: $l= sqrt( $w*$w / $l ); $_ *= $l for @d; my @box; my @s= ( -1, 1 ); # Sign to apply (- or +) for my $s ( 0, 1 ) { # Index into @s # $p==0 for A, $p==1 for B for my $p ( $s, !$s ) { # Which point for my $c ( 0, 1 ) { # Which coordinate # Push the selected coordinate push @box, $_[2*$p+$c] + $s[$s^$c]*$d[!$c]; } } } return @box; } while( ) { last if !/\S/; my @line= split ' '; $line[-1] **= 0.5; my @box= line2box( @line ); printf qq[A line from A( %5.1f, %5.1f )$/] . qq[ to B( %5.1f, %5.1f )$/] . qq[of width sqrt( %5.1f )$/] . qq[is a box, counter-clock-wise:$/] . qq[ W( %5.1f, %5.1f )$/] . qq[ X( %5.1f, %5.1f )$/] . qq[ Y( %5.1f, %5.1f )$/] . qq[ Z( %5.1f, %5.1f )$/] . $/ , @line[0..3], $line[4]**2, , @box; }