File Coverage

blib/lib/Math/Grid/Coordinates.pm
Criterion Covered Total %
statement 42 48 87.5
branch 3 6 50.0
condition 2 5 40.0
subroutine 10 10 100.0
pod 6 6 100.0
total 63 75 84.0


line stmt bran cond sub pod time code
1             package Math::Grid::Coordinates;
2              
3 2     2   27464 use Moose;
  2         598740  
  2         12  
4 2     2   9412 use Moose::Util::TypeConstraints;
  2         2  
  2         16  
5              
6 2     2   3868 use List::AllUtils qw/max/;
  2         14910  
  2         176  
7 2     2   952 use POSIX qw/ceil/;
  2         8953  
  2         10  
8              
9             # number of items
10             has [ qw/grid_width grid_height/ ] => ( is => 'rw', isa => 'Int' );
11              
12             # item size
13             has [ qw/item_width item_height/ ] => ( is => 'rw', isa => 'Num' );
14              
15             # gutter border
16             has [ qw/gutter border/ ] => ( is => 'rw', isa => 'Num' );
17              
18             subtype 'Seq', as 'Str', where { /[h,v]/i };
19             has arrange => ( is => 'rw', isa => 'Seq', default => sub { 'h' } );
20              
21             # has item_sizes => ( is => 'rw', isa => 'ArrayRef[ArrayRef[Num]]' );
22              
23              
24             around BUILDARGS => sub {
25             my $orig = shift;
26             my $class = shift;
27              
28             if ( !ref $_[0] ) {
29            
30             my %h;
31             @h{qw/grid_width grid_height item_width item_height gutter border/} = grep { /[^a-z]/i } @_;
32              
33             ($h{arrange}) = (grep { /^[h,v]i/ } @_) || ('h');
34             $h{gutter} ||= 0;
35             $h{border} ||= 0;
36             return $class->$orig( \%h );
37             } else {
38             return $class->$orig(@_);
39             }
40             };
41              
42             sub total_height {
43 1     1 1 1 my $self = shift;
44 1         23 return $self->border + $self->item_height * $self->grid_height + $self->gutter * ($self->grid_height - 1) + $self->border
45             };
46              
47             sub total_width {
48 1     1 1 3 my $self = shift;
49 1         29 return $self->border + $self->item_width * $self->grid_width + $self->gutter * ($self->grid_width - 1) + $self->border
50             };
51              
52             sub bbox {
53 1     1 1 4 my $self = shift;
54 1         3 my ($w, $h) = ($self->total_width, $self->total_height);
55 1 50       7 return wantarray ? ($w, $h) : [ $w, $h ];
56             }
57              
58             sub sequence {
59 2     2 1 3 my $self = shift;
60 2         2 my ($gw, $gh) = map { $self->$_ } qw/grid_width grid_height/;
  4         101  
61 2         1 my @sequence;
62              
63 2 50       47 if (lc($self->arrange) eq 'v') {
64 0         0 for my $x (0..$gw-1) { for my $y (0..$gh-1) { push @sequence, [$x, $y] } }
  0         0  
  0         0  
65             } else {
66 2         6 for my $y (0..$gh-1) { for my $x (0..$gw-1) { push @sequence, [$x, $y] } }
  8         8  
  24         25  
67             }
68 2         10 return @sequence;
69             }
70              
71             # sub position {
72             # my $self = shift;
73             # my ($x, $y, $x1, $y1, $x2, $y2) = @_;
74             # my ($gw, $gh, $iw, $ih, $gt, $pb) = map { $self->$_ } qw/grid_width grid_height item_width item_height gutter border/;
75              
76             # # $_->[0] = $iw * $_->[0] + ($gt * $_->[0]) + $pb;
77             # # $_->[1] = $ih * $_->[1] + ($gt * $_->[1]) + $pb
78             # }
79              
80             sub positions {
81 1     1 1 1 my $self = shift;
82 1         1 my ($x1, $y1, $x2, $y2) = @_;
83 1   50     2 for ($x1, $y1) { $_ ||= 0 };
  2         13  
84 1         2 my ($gw, $gh, $iw, $ih, $gt, $pb) = map { $self->$_ } qw/grid_width grid_height item_width item_height gutter border/;
  6         146  
85              
86             # first assign positions in terms of page coordinates
87 1         3 my @grid = $self->sequence;
88              
89             # then calculate and assign the actual position
90 1         2 for (@grid) {
91 12         12 $_->[0] = $iw * $_->[0] + ($gt * $_->[0]) + $pb + $x1;
92 12         12 $_->[1] = $ih * $_->[1] + ($gt * $_->[1]) + $pb + $y1
93             };
94              
95 1 50 33     5 if (defined $x2 || defined $y2) { for (@grid) {
  0         0  
96 0         0 $_->[2] = $_->[0] + $x2;
97 0         0 $_->[3] = $_->[1] + $y2;
98             } }
99            
100 1         7 return @grid;
101             }
102              
103             sub numbers {
104 1     1 1 2 my $self = shift;
105 1         31 return (1..($self->grid_width * $self->grid_height))
106             }
107              
108             __PACKAGE__->meta->make_immutable;
109              
110             1;
111              
112             #################### pod generated by Pod::Autopod - keep this line to make pod updates possible ####################
113              
114             =head1 NAME
115              
116             Grid - create geometric grids
117              
118             =head1 SYNOPSYS
119              
120             use Grid;
121              
122             my $grid = Grid->new($grid_width, $grid_height, $item_width, $item_height, $gutter, $border, $arrangement);
123              
124             =head1 DESCRIPTION
125              
126             Grid creates an array of x-y positions for items of a given height and wdith arranged in a grid. This is used to create grid layouts on a page, or repeate items on a number of pages of the same size.
127              
128             =head1 REQUIRES
129              
130             L<POSIX>
131              
132             L<List::AllUtils>
133              
134             L<Moose::Util::TypeConstraints>
135              
136             L<Moose>
137              
138              
139             =head1 METHODS
140              
141             =head2 bbox
142              
143             $grid->bbox();
144              
145             Returns the total bounding box of the grid
146              
147             =head2 numbers
148              
149             $grid->numbers();
150              
151             Returns the sequence item numbers, with the top left item as item 1.
152              
153             +---------+---------+---------+---------+
154             | | | | |
155             | 1 | 2 | 3 | 4 |
156             | | | | |
157             +---------+---------+---------+---------+
158             | | | | |
159             | 5 | 6 | 7 | 8 |
160             | | | | |
161             +---------+---------+---------+---------+
162             | | | | |
163             | 9 | 10 | 11 | 12 |
164             | | | | |
165             +---------+---------+---------+---------+
166              
167             =head2 sequence
168              
169             $grid->sequence();
170              
171             Returns the sequence of x-y grid item coordinates, with the top left item as item C<[0, 0]>, the next one (assuming a horizontal arrangement) being C<[1, 0]> etc.
172              
173             +---------+---------+---------+---------+
174             | | | | |
175             | [0, 0] | [0, 1] | [0, 2] | [0, 3] |
176             | | | | |
177             +---------+---------+---------+---------+
178             | | | | |
179             | [1, 0] | [1, 1] | [1, 2] | [1, 3] |
180             | | | | |
181             +---------+---------+---------+---------+
182             | | | | |
183             | [2, 0] | [2, 1] | [2, 2] | [2, 3] |
184             | | | | |
185             +---------+---------+---------+---------+
186              
187             =head2 positions
188              
189             $grid->positions();
190              
191             Returns the sequence of x-y grid coordinates, taking optional offsets. If two offsets are provided, the x-y position is offset accordingly, and if four are provided, it returns a boumding box.
192              
193             =head2 total_height
194              
195             $grid->total_height();
196              
197             The total height of the grid
198              
199             =head2 total_width
200              
201             $grid->total_width();
202              
203             The total width of the grid
204              
205             =head1 To do
206              
207             =over 4
208              
209             =item *
210              
211             Allow for different vertical and horizontal gutters
212              
213             =item *
214              
215             Allow for different top, bottom, left right borders
216              
217             =item *
218              
219             Allow for bottom or top start of grid
220              
221             =back
222              
223             =cut