#!/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; } #### __END__ 1 0 1 5 4 1 1 6 1 16 -1 -2 2 1 8 A line from A( 1.0, 0.0 ) to B( 1.0, 5.0 ) of width sqrt( 4.0 ) is a box, counter-clock-wise: W( 2.0, 0.0 ) X( 2.0, 5.0 ) Y( 0.0, 5.0 ) Z( 0.0, 0.0 ) w=2 |<--->| | (Y)(B)(X) | # 4+ # | # 3+ # | # 2+ # | # 1+ # | # --+--+-(Z)(A)(W)-+-- -2 -1 0 1 2 A line from A( 1.0, 1.0 ) to B( 6.0, 1.0 ) of width sqrt( 16.0 ) is a box, counter-clock-wise: W( 1.0, -1.0 ) X( 6.0, -1.0 ) Y( 6.0, 3.0 ) Z( 1.0, 3.0 ) | 4+ | 3+ (Z) (Y) --- | ^ 2+ | | | 1+ (A)############(B) w=4 | | --+--+--+--+--+--+--+--+--+- | -1 0 1 2 3 4 5 6 7 v -1+ (W) (X) --- | -2+ | A line from A( -1.0, -2.0 ) to B( 2.0, 1.0 ) of width sqrt( 8.0 ) is a box, counter-clock-wise: W( 0.0, -3.0 ) X( 3.0, 0.0 ) Y( 1.0, 2.0 ) Z( -2.0, -1.0 ) | 3+ / | \ 2+ (Y) w=2*(2**.5) | \ 1+ (B) / | // --+--+--+--+--+--+-(X)-+-- -3 -2 -1 0//1 2 3 4 (Z) -1+ //| (A) -2 | -3(W) | -4+ | #### for my $p ( $s, !$s ) { # Which point