|
|
@ -1,7 +1,3 @@ |
|
|
|
=head1 HexGrid::Path |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=cut |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package HexGrid::Path; |
|
|
|
package HexGrid::Path; |
|
|
|
|
|
|
|
|
|
|
|
use v5.30; |
|
|
|
use v5.30; |
|
|
@ -57,14 +53,18 @@ sub clone_settings($this) |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Given a Path that may not be entirely within a given Grid, |
|
|
|
|
|
|
|
# reduce the Path to smaller subpaths each fully contained in the Grid. |
|
|
|
sub splinter($this, $grid) |
|
|
|
sub splinter($this, $grid) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Collection of subpaths to be generated and returned |
|
|
|
|
|
|
|
# Each will have the id of the original path proceeded by its index, e.g. My-Path-0 |
|
|
|
my @splinters; |
|
|
|
my @splinters; |
|
|
|
my $in_splinter = 0; |
|
|
|
my $in_splinter = 0; |
|
|
|
|
|
|
|
|
|
|
|
# If the base path sources at an edge, and the first tile is present, |
|
|
|
# If the base path sources at an edge, and the first tile is present, |
|
|
|
# the first splinter must source at the same edge |
|
|
|
# the first splinter must source at the same edge |
|
|
|
# (the splinter implicitly exists since the first tile is present) |
|
|
|
# (the splinter implicitly exists since the first tile is present) |
|
|
|
if($this->starts_from && $grid->get_tile_at($this->{tiles}[0]{nw}, $this->{tiles}[0]{sw})) |
|
|
|
if($this->starts_from && $grid->get_tile_at($this->{tiles}[0]{nw}, $this->{tiles}[0]{sw})) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -74,6 +74,7 @@ sub splinter($this, $grid) |
|
|
|
$splinter->{starts_from} = $this->starts_from; |
|
|
|
$splinter->{starts_from} = $this->starts_from; |
|
|
|
push @splinters, $splinter; |
|
|
|
push @splinters, $splinter; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
# We need to reference the preceeding tile in the loop, so a foreach won't suffice |
|
|
|
for(my $i = 0; $i <= $#{$this->tiles}; $i++) |
|
|
|
for(my $i = 0; $i <= $#{$this->tiles}; $i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
unless($in_splinter) |
|
|
|
unless($in_splinter) |
|
|
@ -114,7 +115,8 @@ sub splinter($this, $grid) |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
# In a splinter but tile not present, set previous tile sink to this missing tile |
|
|
|
# In a splinter but tile not present, end splinter |
|
|
|
|
|
|
|
# and set previous tile sink to this missing tile |
|
|
|
$in_splinter = 0; |
|
|
|
$in_splinter = 0; |
|
|
|
my $ending_edge = get_edge_direction($this->{tiles}[$i-1], $this->{tiles}[$i]); |
|
|
|
my $ending_edge = get_edge_direction($this->{tiles}[$i-1], $this->{tiles}[$i]); |
|
|
|
unless($ending_edge) |
|
|
|
unless($ending_edge) |
|
|
@ -144,6 +146,7 @@ sub render($this, $grid, $svg) |
|
|
|
return unless @{$this->tiles}; |
|
|
|
return unless @{$this->tiles}; |
|
|
|
|
|
|
|
|
|
|
|
my $g = $svg->g(id => $this->id, class => $this->css_class); |
|
|
|
my $g = $svg->g(id => $this->id, class => $this->css_class); |
|
|
|
|
|
|
|
# We will be destructively processing the tile array, so copy first |
|
|
|
my @tiles = @{$this->tiles}; |
|
|
|
my @tiles = @{$this->tiles}; |
|
|
|
my $current_tile = shift @tiles; |
|
|
|
my $current_tile = shift @tiles; |
|
|
|
|
|
|
|
|
|
|
@ -163,7 +166,7 @@ sub render($this, $grid, $svg) |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
# line from starts_from to the centre |
|
|
|
# Line from starts_from to the centre |
|
|
|
$g->line(x1 => $x1, y1 => $y1, x2 => $cx, y2 => $cy, |
|
|
|
$g->line(x1 => $x1, y1 => $y1, x2 => $cx, y2 => $cy, |
|
|
|
stroke => $this->colour, style => $this->style, class => $this->css_class); |
|
|
|
stroke => $this->colour, style => $this->style, class => $this->css_class); |
|
|
|
} |
|
|
|
} |
|
|
@ -172,13 +175,14 @@ sub render($this, $grid, $svg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if($this->ends_to) |
|
|
|
if($this->ends_to) |
|
|
|
{ |
|
|
|
{ |
|
|
|
# line from the centre to ends_to |
|
|
|
# Line from the centre to ends_to |
|
|
|
my ($x2, $y2) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $this->ends_to); |
|
|
|
my ($x2, $y2) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $this->ends_to); |
|
|
|
$g->line(x1 => $cx, y1 => $cy, x2 => $x2, y2 => $y2, |
|
|
|
$g->line(x1 => $cx, y1 => $cy, x2 => $x2, y2 => $y2, |
|
|
|
stroke => $this->colour, style => $this->style, class => $this->css_class); |
|
|
|
stroke => $this->colour, style => $this->style, class => $this->css_class); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
# Point at centre |
|
|
|
$g->circle(cx => $cx, cy => $cy, |
|
|
|
$g->circle(cx => $cx, cy => $cy, |
|
|
|
r => $this->{style}{'stroke-width'} // $DEFAULT_WIDTH, |
|
|
|
r => $this->{style}{'stroke-width'} // $DEFAULT_WIDTH, |
|
|
|
fill => $this->colour, style => $this->style, class => $this->css_class); |
|
|
|
fill => $this->colour, style => $this->style, class => $this->css_class); |
|
|
@ -187,6 +191,7 @@ sub render($this, $grid, $svg) |
|
|
|
return $g; |
|
|
|
return $g; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Setup iterated variables |
|
|
|
my ($x0, $x, $y0, $y); |
|
|
|
my ($x0, $x, $y0, $y); |
|
|
|
my $path_spec; |
|
|
|
my $path_spec; |
|
|
|
my $previous_tile = $current_tile; |
|
|
|
my $previous_tile = $current_tile; |
|
|
@ -198,25 +203,29 @@ sub render($this, $grid, $svg) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
($x, $y) = $grid->coords_of_edge($previous_tile->nw, $previous_tile->sw, $next_edge); |
|
|
|
($x, $y) = $grid->coords_of_edge($previous_tile->nw, $previous_tile->sw, $next_edge); |
|
|
|
|
|
|
|
my $previous_edge; |
|
|
|
|
|
|
|
my $next_tile; |
|
|
|
|
|
|
|
|
|
|
|
if($this->starts_from) |
|
|
|
if($this->starts_from) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
# Go from source edge to edge with next tile |
|
|
|
($x0, $y0) = $grid->coords_of_edge($previous_tile->nw, $previous_tile->sw, $this->starts_from); |
|
|
|
($x0, $y0) = $grid->coords_of_edge($previous_tile->nw, $previous_tile->sw, $this->starts_from); |
|
|
|
$path_spec .= "M $x0,$y0 "; |
|
|
|
|
|
|
|
my ($cx, $cy) = $grid->coords_of_centre($previous_tile->nw, $previous_tile->sw); |
|
|
|
my ($cx, $cy) = $grid->coords_of_centre($previous_tile->nw, $previous_tile->sw); |
|
|
|
$path_spec .= "Q $cx,$cy $x,$y"; |
|
|
|
$path_spec .= "M $x0,$y0 Q $cx,$cy $x,$y"; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
# Go from centre to edge with next tile |
|
|
|
($x0, $y0) = $grid->coords_of_centre($previous_tile->nw, $previous_tile->sw); |
|
|
|
($x0, $y0) = $grid->coords_of_centre($previous_tile->nw, $previous_tile->sw); |
|
|
|
$path_spec .= "M $x0,$y0 L $x,$y"; |
|
|
|
$path_spec .= "M $x0,$y0 L $x,$y"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
my $previous_edge; # not defined yet |
|
|
|
# This loop adds all the intermediate segments |
|
|
|
my $next_tile; # not defined yet |
|
|
|
# Importantly, all go from edge to edge |
|
|
|
while (@tiles) |
|
|
|
while (@tiles) |
|
|
|
{ |
|
|
|
{ |
|
|
|
$next_tile = shift @tiles; |
|
|
|
$next_tile = shift @tiles; |
|
|
|
$previous_edge = -$next_edge; |
|
|
|
$previous_edge = -$next_edge; #Edge from previous-to-current is opposite the previous current-to-next |
|
|
|
$next_edge = get_edge_direction($current_tile, $next_tile); |
|
|
|
$next_edge = get_edge_direction($current_tile, $next_tile); |
|
|
|
unless($next_edge) |
|
|
|
unless($next_edge) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -224,6 +233,7 @@ sub render($this, $grid, $svg) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Curve from previous edge to next edge controlled through current centre |
|
|
|
my ($qx,$qy) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); |
|
|
|
my ($qx,$qy) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); |
|
|
|
($x,$y) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $next_edge); |
|
|
|
($x,$y) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $next_edge); |
|
|
|
|
|
|
|
|
|
|
@ -236,12 +246,14 @@ sub render($this, $grid, $svg) |
|
|
|
# $next_edge is the last used edge, so use it's opposite for the source of last line |
|
|
|
# $next_edge is the last used edge, so use it's opposite for the source of last line |
|
|
|
if($this->ends_to) |
|
|
|
if($this->ends_to) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
# Go from edge with previous tile to sink edge |
|
|
|
($x, $y) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); |
|
|
|
($x, $y) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); |
|
|
|
my ($xe, $ye) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $this->ends_to); |
|
|
|
my ($xe, $ye) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $this->ends_to); |
|
|
|
$path_spec .= "Q $x,$y $xe,$ye"; |
|
|
|
$path_spec .= "Q $x,$y $xe,$ye"; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
# Go from edge with previous tile to centre |
|
|
|
($x, $y) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); |
|
|
|
($x, $y) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); |
|
|
|
$path_spec .= " L $x,$y"; |
|
|
|
$path_spec .= " L $x,$y"; |
|
|
|
} |
|
|
|
} |
|
|
@ -252,8 +264,4 @@ sub render($this, $grid, $svg) |
|
|
|
return $g; |
|
|
|
return $g; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
=back |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=cut |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1; |
|
|
|
1; |
|
|
|