diff --git a/HexGrid/Path.pm b/HexGrid/Path.pm index 957c54f..09780cf 100644 --- a/HexGrid/Path.pm +++ b/HexGrid/Path.pm @@ -1,7 +1,3 @@ -=head1 HexGrid::Path - -=cut - package HexGrid::Path; 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) { + # 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 $in_splinter = 0; # 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) 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; 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++) { unless($in_splinter) @@ -114,7 +115,8 @@ sub splinter($this, $grid) } 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; my $ending_edge = get_edge_direction($this->{tiles}[$i-1], $this->{tiles}[$i]); unless($ending_edge) @@ -144,6 +146,7 @@ sub render($this, $grid, $svg) return unless @{$this->tiles}; 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 $current_tile = shift @tiles; @@ -163,7 +166,7 @@ sub render($this, $grid, $svg) } 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, stroke => $this->colour, style => $this->style, class => $this->css_class); } @@ -172,13 +175,14 @@ sub render($this, $grid, $svg) { 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); $g->line(x1 => $cx, y1 => $cy, x2 => $x2, y2 => $y2, stroke => $this->colour, style => $this->style, class => $this->css_class); } else { + # Point at centre $g->circle(cx => $cx, cy => $cy, r => $this->{style}{'stroke-width'} // $DEFAULT_WIDTH, fill => $this->colour, style => $this->style, class => $this->css_class); @@ -187,6 +191,7 @@ sub render($this, $grid, $svg) return $g; } + # Setup iterated variables my ($x0, $x, $y0, $y); my $path_spec; my $previous_tile = $current_tile; @@ -198,25 +203,29 @@ sub render($this, $grid, $svg) return; } ($x, $y) = $grid->coords_of_edge($previous_tile->nw, $previous_tile->sw, $next_edge); + my $previous_edge; + my $next_tile; + 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); - $path_spec .= "M $x0,$y0 "; 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 { + # Go from centre to edge with next tile ($x0, $y0) = $grid->coords_of_centre($previous_tile->nw, $previous_tile->sw); $path_spec .= "M $x0,$y0 L $x,$y"; } - my $previous_edge; # not defined yet - my $next_tile; # not defined yet + # This loop adds all the intermediate segments + # Importantly, all go from edge to edge while (@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); unless($next_edge) { @@ -224,6 +233,7 @@ sub render($this, $grid, $svg) 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); ($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 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); my ($xe, $ye) = $grid->coords_of_edge($current_tile->nw, $current_tile->sw, $this->ends_to); $path_spec .= "Q $x,$y $xe,$ye"; } else { + # Go from edge with previous tile to centre ($x, $y) = $grid->coords_of_centre($current_tile->nw, $current_tile->sw); $path_spec .= " L $x,$y"; } @@ -252,8 +264,4 @@ sub render($this, $grid, $svg) return $g; } -=back - -=cut - 1;