File Coverage

blib/lib/Attach/Stuff.pm
Criterion Covered Total %
statement 35 35 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod 2 2 100.0
total 46 46 100.0


line stmt bran cond sub pod time code
1             # Copyright (c) 2015 Timm Murray
2             # All rights reserved.
3             #
4             # Redistribution and use in source and binary forms, with or without
5             # modification, are permitted provided that the following conditions are met:
6             #
7             # * Redistributions of source code must retain the above copyright notice,
8             # this list of conditions and the following disclaimer.
9             # * Redistributions in binary form must reproduce the above copyright
10             # notice, this list of conditions and the following disclaimer in the
11             # documentation and/or other materials provided with the distribution.
12             #
13             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23             # POSSIBILITY OF SUCH DAMAGE.
24             package Attach::Stuff;
25              
26             # ABSTRACT: Attach stuff to other stuff
27 2     2   19243 use v5.14;
  2         6  
  2         85  
28 2     2   11 use warnings;
  2         3  
  2         67  
29 2     2   1402 use Moose;
  2         809345  
  2         20  
30 2     2   12939 use namespace::autoclean;
  2         2579  
  2         11  
31 2     2   1177 use SVG;
  2         23885  
  2         13  
32              
33             # According to SVG spec, there are 3.543307 pixels per mm. See:
34             # http://www.w3.org/TR/SVG/coords.html#Units
35 2     2   1503 use constant MM_IN_PX => 3.543307;
  2         4  
  2         584  
36              
37             has 'width' => (
38             is => 'rw',
39             isa => 'Num',
40             required => 1,
41             );
42             has 'height' => (
43             is => 'rw',
44             isa => 'Num',
45             required => 1,
46             );
47             has 'screw_default_radius' => (
48             is => 'rw',
49             isa => 'Num',
50             required => 1,
51             );
52             has 'screw_holes' => (
53             is => 'rw',
54             isa => 'ArrayRef[ArrayRef[Num]]',
55             required => 1,
56             );
57             has 'stroke_width' => (
58             is => 'rw',
59             isa => 'Num',
60             required => 1,
61             default => sub { 0.3 },
62             );
63              
64              
65             sub draw
66             {
67 1     1 1 7 my ($self) = @_;
68 1         31 my $width = $self->width;
69 1         25 my $height = $self->height;
70 1         31 my $screw_default_radius = $self->screw_default_radius;
71 1         27 my $stroke_width = $self->stroke_width;
72 1         1 my @screw_holes = @{ $self->screw_holes };
  1         28  
73              
74 1         4 my $svg = SVG->new(
75             width => $self->mm_to_px( $width ),
76             height => $self->mm_to_px( $height ),
77             );
78              
79 1         281 my $draw = $svg->group(
80             id => 'draw',
81             style => {
82             stroke => 'black',
83             'stroke-width' => $stroke_width,
84             fill => 'none',
85             },
86             );
87              
88             # Draw outline
89 1         57 $draw->rectangle(
90             x => 0,
91             y => 0,
92             width => $self->mm_to_px( $width ),
93             height => $self->mm_to_px( $height ),
94             );
95              
96             # Draw screw holes
97             $draw->circle(
98             cx => $self->mm_to_px( $_->[0] ),
99             cy => $self->mm_to_px( $_->[1] ),
100             r => $self->mm_to_px( $screw_default_radius ),
101 1         42 ) for @screw_holes;
102              
103 1         33 return $svg;
104             }
105              
106              
107             sub mm_to_px
108             {
109 10     10 1 43 my ($self, $mm) = @_;
110 10         28 return $mm * MM_IN_PX;
111             }
112              
113              
114 2     2   11 no Moose;
  2         5  
  2         16  
115             __PACKAGE__->meta->make_immutable;
116             1;
117             __END__
118              
119             =head1 NAME
120              
121             Attach::Stuff - Attach stuff to other stuff
122              
123             =head1 SYNOPSIS
124              
125             use Attach::Stuff;
126              
127             # You've got a board that's 26x34 mm, with two screw holes with a
128             # 2 mm diameter, spaced 3mm from the edge
129             my $attach = Attach::Stuff->new({
130             width => 26,
131             height => 34,
132             stroke_width => 0.3,
133             screw_default_radius => 1.25, # 2mm diameter, plus some wiggle room
134             screw_holes => [
135             [ 3, 3 ],
136             [ 26 - 3, 3 ],
137             ],
138             });
139             my $svg = $attach->draw;
140             print $svg->xmlify;
141              
142             =head1 DESCRIPTION
143              
144             You've got stuff, like a PCB board, that needs to be attached to other stuff,
145             like a lasercut enclosure. How do you attach the stuff to the other stuff?
146             This is a question we ask a lot when doing homebuilt Internet of Things
147             projects. Perl has the "Internet" half down pat. This module is an attempt to
148             improve the "Things" part.
149              
150             Lasercutters and other CNC machines often work with SVGs. Or more likely SVGs
151             can be converted into something that are converted into G-code by whatever turd
152             of a software package came with your CNC machine. Whatever the case, you can
153             probably start with an SVG and work your way from there.
154              
155             Before you can get there, you need measurements of the board and the location
156             of the screw holes. If you're lucky, you can find full schematics for your
157             board that will tell you the sizes exactly. If not, you'll need to get out
158             some callipers and possibly do some guesswork.
159              
160             Protip: if you had to guess on some of the locations, etch a prototype into
161             cardboard. Then you can lay the board over the cardboard and see if it matches
162             up right.
163              
164             =head1 METHODS
165              
166             =head2 new
167              
168             Constructor. Has the attributes below. Note that all lengths are measured
169             in millimeters.
170              
171             =over 4
172              
173             =item * width
174              
175             =item * height
176              
177             =item * stroke_width - The width of the lines. Defaults to 0.3.
178              
179             =item * screw_default_radius - All screws will be this radius. Currently, there is no way to specify a screw with any other radius. It's recommended to add a little extra to the radius to fit the screws through.
180              
181             =item * screw_holes - Arrayref of arrayrefs of the x/y coords of screw holes
182              
183             =back
184              
185             =head2 draw
186              
187             Draw based on the parameters given in the constructor. Returns an L<SVG>
188             object.
189              
190             =head2 mm_to_px
191              
192             Takes a measurement in millimeters and returns the length in pixels according
193             to the SVG standard. Useful if you need to draw more complex shapes for your
194             board after Attach::Stuff did the basics. See the C<examples/rpi_camera.pl>
195             file in this distribution for an example of this.
196              
197              
198             =head1 SEE ALSO
199              
200             L<SVG>
201              
202             =head1 LICENSE
203              
204              
205             Copyright (c) 2015, Timm Murray
206             All rights reserved.
207              
208             Redistribution and use in source and binary forms, with or without modification, are
209             permitted provided that the following conditions are met:
210              
211             * Redistributions of source code must retain the above copyright notice, this list of
212             conditions and the following disclaimer.
213             * Redistributions in binary form must reproduce the above copyright notice, this list of
214             conditions and the following disclaimer in the documentation and/or other materials
215             provided with the distribution.
216              
217             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
218             OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
219             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
220             COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
221             EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
222             SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
223             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
224             TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
225             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
226              
227             =cut