KiCad Pcbnew Python Scripting
Loading...
Searching...
No Matches
FootprintWizardBase.py
Go to the documentation of this file.
2# This program source code file is part of KiCad, a free EDA CAD application.
3#
4# Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19# MA 02110-1301, USA.
20#
21
22from __future__ import division
23import pcbnew
24import math
25
26
28 """!
29 A class to simplify many aspects of footprint creation, leaving only
30 the footprint specific routines to the wizards themselves.
31
32 Inherit this class to make a new wizard.
33
34 Provides simplified access to helpers like drawing functions, a transform
35 matrix stack and simple parameter checking.
36
37 Generally, you need to implement:
38 GetValue()
42 GetName()
44 """
45
46 # Copy units from pcbnew
47 uMM = pcbnew.uMM
48 uMils = pcbnew.uMils
49 uFloat = pcbnew.uFloat
50 uInteger = pcbnew.uInteger
51 uBool = pcbnew.uBool
52 uRadians = pcbnew.uRadians
53 uDegrees = pcbnew.uDegrees
54 uPercent = pcbnew.uPercent
55 uString = pcbnew.uString
56
57 def __init__(self):
60
61 def GetName(self):
62 """!
63 Return the name of the footprint wizard
64 """
65 raise NotImplementedError
66
67 def GetDescription(self):
68 """!
69 Return the footprint wizard description
70 """
71 raise NotImplementedError
72
73 def GetValue(self):
74 """!
75 Return the value (name) of the generated footprint
76 """
77 raise NotImplementedError
78
80 """!
81 Footprint parameter specification is done here
82 """
83 raise NotImplementedError
84
85 def CheckParameters(self):
86 """!
87 Any custom parameter checking should be performed here
88 """
89 raise NotImplementedError
90
92 """!
93 Draw the footprint.
94
95 This is specific to each footprint class, you need to implement
96 this to draw what you want
97 """
98 raise NotImplementedError
99
100 # Do not override this method!
101 def BuildFootprint(self):
102 """!
103 Actually make the footprint. We defer all but the set-up to
104 the implementing class
105 """
106
108 self.modulemodule = pcbnew.FOOTPRINT(None) # create a new module
109
110 # Perform default checks on all parameters
111 for p in self.params:
112 p.ClearErrors()
113 p.Check() # use defaults
114
115 self.CheckParameters() # User error checks
116
117 if self.AnyErrors(): # Errors were detected!
118
119 self.buildmessagesbuildmessages = ("Cannot build footprint: "
120 "Parameters have errors:\n")
121
122 for p in self.params:
123 if len(p.error_list) > 0:
124 self.buildmessagesbuildmessages += "['{page}']['{name}']:\n".format(
125 page=p.page, name=p.name)
126
127 for error in p.error_list:
128 self.buildmessagesbuildmessages += "\t" + error + "\n"
129
130 return
131
133 "Building new {name} footprint with the following parameters:\n"
134 .format(name=self.name))
135
136 self.buildmessagesbuildmessages += self.Show()
137
139 self.modulemodule)
140
141 self.modulemodule.SetValue(self.GetValueGetValue())
142 self.modulemodule.SetReference("%s**" % self.GetReferencePrefix())
143
144 fpid = pcbnew.LIB_ID("", self.modulemodule.GetValue()) # the lib name (empty) and the name in library
145 self.modulemodule.SetFPID(fpid)
146
147 self.SetModule3DModel() # add a 3D module if specified
148
149 thick = self.GetTextThickness()
150
151 self.modulemodule.Reference().SetTextThickness(thick)
152 self.modulemodule.Value().SetTextThickness(thick)
153
154 self.BuildThisFootprint() # implementer's build function
155
156 return
157
159 """!
160 If your plug-in sets a 3D model, override this function
161 """
162 pass
163
164 def GetTextSize(self):
165 """!
166 Get the default text size for the footprint. Override to change it.
167
168 Defaults to IPC nominal of 1.0mm
169 """
170 return pcbnew.FromMM(1.0)
171
173 """!
174 Thicker than IPC guidelines (10% of text height = 0.12mm)
175 as 5 wires/mm is a common silk screen limitation
176 """
177 return pcbnew.FromMM(0.15)
178
179
181 """!
182 Collection of handy functions to simplify drawing shapes from within
183 footprint wizards
184
185 A "drawing context" is provided which can be used to set and retain
186 settings such as line thickness and layer. The DC also contains a
187 "transform stack", which allows easy positioning and transforming of
188 drawn elements without lots of geometric book-keeping.
189 """
190
191 # directions (in degrees, compass-like)
192 dirN = 0
193 dirNE = 45
194 dirE = 90
195 dirSE = 135
196 dirS = 180
197 dirSW = 225
198 dirW = 270
199 dirNW = 315
200
201 # Flip constants
202 flipNone = 0 # no flip transform
203 flipX = 1 # flip X values, i.e. about the Y-axis
204 flipY = 2 # flip Y values, i.e. about the X-axis
205 flipBoth = 3 # flip X and Y values, equivalent to a 180-degree rotation
206
207 xfrmIDENTITY = [1, 0, 0, 0, 1, 0] # no transform
208
209 # these values come from our KiCad Library Convention 0.11
210 defaultLineThickness = pcbnew.FromMM(0.15)
211
213 return pcbnew.F_SilkS
214
216 return pcbnew.F_Fab
217
218 def __init__(self, module):
219 self.module = module
220 # drawing context defaults
221 self.dc = {
222 'layer': self.DefaultGraphicLayer(),
223 'lineThickness': self.defaultLineThickness,
224 'transforms': [],
225 'transform': self.xfrmIDENTITY
226 }
227
228 def PushTransform(self, mat):
229 """!
230 Add a transform to the top of the stack and recompute the
231 overall transform
232
233 @param mat: the transform matrix to add to the stack
234 """
235 self.dc['transforms'].append(mat)
237
238 def PopTransform(self, num=1):
239 """!
240 Remove a transform from the top of the stack and recompute the
241 overall transform
242
243 @param num: the number of transforms to pop from the stack.
244 @return the last popped transform
245 """
246
247 for i in range(num):
248 mat = self.dc['transforms'].pop()
250 return mat
251
252 def ResetTransform(self):
253 """!
254 Reset the transform stack to the identity matrix.
255 """
256 self.dc['transforms'] = []
258
259 def _ComposeMatricesWithIdentity(self, mats):
260 """!
261 Compose a sequence of matrices together by sequential
262 pre-multiplication with the identity matrix.
263
264 @param mats: list of matrices to compose
265 @return: the composed transform matrix
266 """
267
268 x = self.xfrmIDENTITY
269
270 for mat in mats:
271 # Pre-compose with each transform in turn
272 x = [
273 x[0] * mat[0] + x[1] * mat[3],
274 x[0] * mat[1] + x[1] * mat[4],
275 x[0] * mat[2] + x[1] * mat[5] + x[2],
276 x[3] * mat[0] + x[4] * mat[3],
277 x[3] * mat[1] + x[4] * mat[4],
278 x[3] * mat[2] + x[4] * mat[5] + x[5]]
279
280 return x
281
283 """!
284 Re-compute the transform stack into a single transform and
285 store in the DC
286 """
287 self.dc['transform'] = self._ComposeMatricesWithIdentity(
288 self.dc['transforms'])
289
290 def TransformTranslate(self, x, y, push=True):
291 """!
292 Set up and return a transform matrix representing a translation
293 optionally pushing onto the stack
294
295 ( 1 0 x )
296 ( 0 1 y )
297
298 @param x: translation in x-direction
299 @param y: translation in y-direction
300 @param push: add this transform to the current stack
301 @return the generated transform matrix
302 """
303 mat = [1, 0, x, 0, 1, y]
304
305 if push:
306 self.PushTransform(mat)
307 return mat
308
309 def TransformFlipOrigin(self, flip, push=True):
310 """!
311 Set up and return a transform matrix representing a horizontal,
312 vertical or both flip about the origin
313
314 @param flip: one of flipNone, flipX, flipY, flipBoth
315 @param push: add this transform to the current stack
316 @return the generated transform matrix
317 """
318 mat = None
319 if flip == self.flipX:
320 mat = [-1, 0, 0, 0, 1, 0]
321 elif flip == self.flipY:
322 mat = [1, 0, 0, 0, -1, 0]
323 elif flip == self.flipBoth:
324 mat = [-1, 0, 0, 0, -1, 0]
325 elif flip == self.flipNone:
326 mat = self.xfrmIDENTITY
327 else:
328 raise ValueError
329
330 if push:
331 self.PushTransform(mat)
332 return mat
333
334 def TransformFlip(self, x, y, flip=flipNone, push=True):
335 """!
336 Set up and return a transform matrix representing a horizontal,
337 vertical or both flip about a point (x,y)
338
339 This is performed by a translate-to-origin, flip, translate-
340 back sequence.
341
342 @param x: the x coordinate of the flip point
343 @param y: the y coordinate of the flip point
344 @param flip: one of flipNone, flipX, flipY, flipBoth
345 @param push: add this transform to the current stack
346 @return the generated transform matrix
347 """
348 mats = [self.TransformTranslate(x, y, push=False),
349 self.TransformFlipOrigin(flip, push=False),
350 self.TransformTranslate(-x, -y, push=False)]
351
352 # Distil into a single matrix
353 mat = self._ComposeMatricesWithIdentity(mats)
354
355 if push:
356 self.PushTransform(mat)
357 return mat
358
359 def TransformRotationOrigin(self, rot, push=True):
360 """!
361 Set up and return a transform matrix representing a rotation
362 about the origin, and optionally push onto the stack
363
364 ( cos(t) -sin(t) 0 )
365 ( sin(t) cos(t) 0 )
366
367 @param rot: the rotation angle in degrees
368 @param push: add this transform to the current stack
369 @return the generated transform matrix
370 """
371 rads = rot * math.pi / 180
372 mat = [math.cos(rads), -math.sin(rads), 0,
373 math.sin(rads), math.cos(rads), 0]
374
375 if push:
376 self.PushTransform(mat)
377 return mat
378
379 def TransformRotation(self, x, y, rot, push=True):
380 """!
381 Set up and return a transform matrix representing a rotation
382 about the point (x,y), and optionally push onto the stack
383
384 This is performed by a translate-to-origin, rotate, translate-
385 back sequence
386
387 @param x: the x coordinate of the rotation centre
388 @param y: the y coordinate of the rotation centre
389 @param rot: the rotation angle in degrees
390 @param push: add this transform to the current stack
391 @return the generated transform matrix
392 """
393
394 mats = [self.TransformTranslate(x, y, push=False),
395 self.TransformRotationOrigin(rot, push=False),
396 self.TransformTranslate(-x, -y, push=False)]
397
398 # Distil into a single matrix
399 mat = self._ComposeMatricesWithIdentity(mats)
400
401 if push:
402 self.PushTransform(mat)
403 return mat
404
405 def TransformScaleOrigin(self, sx, sy=None, push=True):
406 """!
407 Set up and return a transform matrix representing a scale about
408 the origin, and optionally push onto the stack
409
410 ( sx 0 0 )
411 ( 0 sy 0 )
412
413 @param sx: the scale factor in the x direction
414 @param sy: the scale factor in the y direction
415 @param push: add this transform to the current stack
416 @return the generated transform matrix
417 """
418
419 if sy is None:
420 sy = sx
421
422 mat = [sx, 0, 0, 0, sy, 0]
423
424 if push:
425 self.PushTransform(mat)
426 return mat
427
428 def TransformPoint(self, x, y, mat=None):
429 """!
430 Return a point (x, y) transformed by the given matrix, or if
431 that is not given, the drawing context transform
432
433 @param x: the x coordinate of the point to transform
434 @param y: the y coordinate of the point to transform
435 @param mat: the transform matrix to use or None to use the current DC's
436 @return: the transformed point as a VECTOR2I
437 """
438
439 if not mat:
440 mat = self.dc['transform']
441
442 return pcbnew.VECTOR2I( (int)(x * mat[0] + y * mat[1] + mat[2]),
443 (int)(x * mat[3] + y * mat[4] + mat[5]) )
444
445 def SetLineThickness(self, lineThickness):
446 """!
447 Set the current pen lineThickness used for subsequent drawing
448 operations
449
450 @param lineThickness: the new line thickness to set
451 """
452 self.dc['lineThickness'] = lineThickness
453
454 def SetLineTickness(self, lineThickness):
455 """!
456 Old version of SetLineThickness.
457 Does the same thing, but is only here for compatibility with old
458 scripts.
459 Set the current pen lineThickness used for subsequent drawing
460 operations
461
462 @param lineThickness: the new line thickness to set
463 """
464 self.SetLineThickness(lineThickness)
465
467 """!
468 Get the current drawing context line thickness
469 """
470 return self.dc['lineThickness']
471
472 def SetLayer(self, layer):
473 """!
474 Set the current drawing layer, used for subsequent drawing
475 operations
476 """
477 self.dc['layer'] = layer
478
479 def GetLayer(self):
480 """!
481 Return the current drawing layer, used for drawing operations
482 """
483 return self.dc['layer']
484
485 def Line(self, x1, y1, x2, y2):
486 """!
487 Draw a line from (x1, y1) to (x2, y2)
488 """
489 outline = pcbnew.PCB_SHAPE(self.module)
490 outline.SetWidth(self.GetLineThickness())
491 outline.SetLayer(self.GetLayer())
492 outline.SetShape(pcbnew.S_SEGMENT)
493 start = self.TransformPoint(x1, y1)
494 end = self.TransformPoint(x2, y2)
495 outline.SetStartEnd(start, end)
496 self.module.Add(outline)
497
498 def Circle(self, x, y, r, filled=False):
499 """!
500 Draw a circle at (x,y) of radius r
501 If filled is true, the thickness and radius of the line will be set
502 such that the circle appears filled
503
504 @param x: the x coordinate of the arc centre
505 @param y: the y coordinate of the arc centre
506 @param r: the circle's radius
507 @param filled: True to draw a filled circle, False to use the current
508 DC line thickness
509 """
510
511 circle = pcbnew.PCB_SHAPE(self.module)
512 start = self.TransformPoint(x, y)
513
514 if filled:
515 circle.SetWidth(r)
516 end = self.TransformPoint(x, y + r/2)
517 else:
518 circle.SetWidth(self.dc['lineThickness'])
519 end = self.TransformPoint(x, y + r)
520
521 circle.SetLayer(self.dc['layer'])
522 circle.SetShape(pcbnew.S_CIRCLE)
523 circle.SetStartEnd(start, end)
524 self.module.Add(circle)
525
526 def MyCmp(self, n1, n2):
527 """
528 replace the cmp() of python2
529 """
530 if n1 < n2:
531 return -1
532 if n1 > n2:
533 return 1
534 return 0
535
536 def Arc(self, cx, cy, sx, sy, angle):
537 """!
538 Draw an arc based on centre, start and angle
539
540 The transform matrix is applied
541
542 Note that this won't work properly if the result is not a
543 circular arc (e.g. a horizontal scale)
544
545 @param cx: the x coordinate of the arc centre
546 @param cy: the y coordinate of the arc centre
547 @param sx: the x coordinate of the arc start point
548 @param sy: the y coordinate of the arc start point
549 @param angle: the arc's central angle (in deci-degrees)
550 """
551 arc = pcbnew.PCB_SHAPE(self.module)
552 arc.SetShape(pcbnew.SHAPE_T_ARC)
553 arc.SetWidth(self.dc['lineThickness'])
554
555 center = self.TransformPoint(cx, cy)
556 start = self.TransformPoint(sx, sy)
557
558 arc.SetLayer(self.dc['layer'])
559
560 # check if the angle needs to be reverse (a flip scaling)
561 if self.MyCmp(self.dc['transform'][0], 0) != self.MyCmp(self.dc['transform'][4], 0):
562 angle = -angle
563
564 arc.SetCenter(center)
565 arc.SetStart(start)
566 arc.SetArcAngleAndEnd(angle, True)
567 #arc.SetLocalCoord()
568 self.module.Add(arc)
569
570 def HLine(self, x, y, l):
571 """!
572 Draw a horizontal line from (x,y), rightwards
573
574 @param x: line start x coordinate
575 @param y: line start y coordinate
576 @param l: line length
577 """
578 self.Line(x, y, x + l, y)
579
580 def VLine(self, x, y, l):
581 """!
582 Draw a vertical line from (x1,y1), downwards
583
584 @param x: line start x coordinate
585 @param y: line start y coordinate
586 @param l: line length
587 """
588 self.Line(x, y, x, y + l)
589
590 def Polyline(self, pts, mirrorX=None, mirrorY=None):
591 """!
592 Draw a polyline, optionally mirroring around the given points
593
594 @param pts: list of polyline vertices (list of (x, y))
595 @param mirrorX: x coordinate of mirror point (None for no x-flip)
596 @param mirrorY: y coordinate of mirror point (None for no y-flip)
597 """
598
599 def _PolyLineInternal(pts):
600 if len(pts) < 2:
601 return
602
603 for i in range(0, len(pts) - 1):
604 self.Line(pts[i][0], pts[i][1], pts[i+1][0], pts[i+1][1])
605
606 if mirrorX is None and mirrorY is None:
607 _PolyLineInternal(pts) # original
608
609 elif mirrorX is not None and mirrorY is not None:
610 self.TransformFlip(mirrorX, mirrorY, self.flipBoth) # both
611 _PolyLineInternal(pts)
612 self.PopTransform()
613
614 elif mirrorX is not None:
615 self.TransformFlip(mirrorX, 0, self.flipX)
616 _PolyLineInternal(pts)
617 self.PopTransform()
618
619 elif mirrorY is not None:
620 self.TransformFlip(0, mirrorY, self.flipY)
621 _PolyLineInternal(pts)
622 self.PopTransform()
623
624 def Reference(self, x, y, size, orientation_degree=0):
625 """!
626 Draw the module's reference as the given point.
627
628 The actual setting of the reference is not done in this drawing
629 aid - that is up to the wizard
630
631 @param x: the x position of the reference
632 @param y: the y position of the reference
633 @param size: the text size (in both directions)
634 @param orientation_degree: text orientation in degrees
635 """
636
637 text_size = pcbnew.VECTOR2I(size, size)
638
639 self.module.Reference().SetPosition( self.TransformPoint(x, y) )
640 self.module.Reference().SetTextSize(text_size)
641 self.module.Reference().SetTextAngle( pcbnew.EDA_ANGLE( orientation_degree, pcbnew.DEGREES_T ) )
642
643 def Value(self, x, y, size, orientation_degree=0):
644 """!
645 As for references, draw the module's value
646
647 @param x: the x position of the value
648 @param y: the y position of the value
649 @param size: the text size (in both directions)
650 @param orientation_degree: text orientation in degrees
651 """
652 text_size = pcbnew.VECTOR2I(size, size)
653
654 self.module.Value().SetPosition(self.TransformPoint(x, y))
655 self.module.Value().SetTextSize(text_size)
657 self.module.Value().SetTextAngle( pcbnew.EDA_ANGLE( orientation_degree, pcbnew.DEGREES_T ) )
658
659 def Box(self, x, y, w, h):
660 """!
661 Draw a rectangular box, centred at (x,y), with given width and
662 height
663
664 @param x: the x coordinate of the box's centre
665 @param y: the y coordinate of the box's centre
666 @param w: the width of the box
667 @param h: the height of the box
668 """
669
670 pts = [[x - w/2, y - h/2], # left
671 [x + w/2, y - h/2], # right
672 [x + w/2, y + h/2], # bottom
673 [x - w/2, y + h/2], # top
674 [x - w/2, y - h/2]] # close
675
676 self.Polyline(pts)
677
678 def NotchedCircle(self, x, y, r, notch_w, notch_h, rotate=0):
679 """!
680 Circle radius r centred at (x, y) with a raised or depressed notch
681 at the top
682 Notch height is measured from the top of the circle radius
683
684 @param x: the x coordinate of the circle's centre
685 @param y: the y coordinate of the circle's centre
686 @param r: the radius of the circle
687 @param notch_w: the width of the notch
688 @param notch_h: the height of the notch
689 @param rotate: the rotation of the whole figure, in degrees
690 """
691
692 self.TransformRotation(x, y, rotate)
693
694 # find the angle where the notch vertical meets the circle
695 angle_intercept = math.asin(notch_w/(2 * r))
696
697 # and find the co-ords of this point
698 sx = math.sin(angle_intercept) * r
699 sy = -math.cos(angle_intercept) * r
700
701 # NOTE: this may be out by a factor of ten one day
702 arc_angle = (math.pi * 2 - angle_intercept * 2) * (1800/math.pi)
703
704 self.Arc(x, y, sx, sy, arc_angle)
705
706 pts = [[sx, sy],
707 [sx, -r - notch_h],
708 [-sx, -r - notch_h],
709 [-sx, sy]]
710
711 self.Polyline(pts)
712 self.PopTransform()
713
714 def NotchedBox(self, x, y, w, h, notchW, notchH, rotate=0):
715 """!
716 Draw a box with a notch in the centre of the top edge
717
718 @param x: the x coordinate of the circle's centre
719 @param y: the y coordinate of the circle's centre
720 @param w: the width of the box
721 @param h: the height of the box
722 @param notchW: the width of the notch
723 @param notchH: the height of the notch
724 @param rotate: the rotation of the whole figure, in degrees
725 """
726
727 self.TransformRotation(x, y, rotate)
728
729 # limit to half the overall width
730 notchW = min(x + w/2, notchW)
731
732 # draw notch
733 self.Polyline([ # three sides of box
734 (x - w/2, y - h/2),
735 (x - w/2, y + h/2),
736 (x + w/2, y + h/2),
737 (x + w/2, y - h/2),
738 # the notch
739 (notchW/2, y - h/2),
740 (notchW/2, y - h/2 + notchH),
741 (-notchW/2, y - h/2 + notchH),
742 (-notchW/2, y - h/2),
743 (x - w/2, y - h/2)
744 ])
745
746 self.PopTransform()
747
748 def BoxWithDiagonalAtCorner(self, x, y, w, h,
749 setback=pcbnew.FromMM(1.27), flip=flipNone):
750 """!
751 Draw a box with a diagonal at the top left corner.
752
753 @param x: the x coordinate of the circle's centre
754 @param y: the y coordinate of the circle's centre
755 @param w: the width of the box
756 @param h: the height of the box
757 @param setback: the set-back of the diagonal, in both x and y
758 @param flip: one of flipNone, flipX, flipY or flipBoth to change the
759 diagonal corner
760 """
761
762 self.TransformFlip(x, y, flip, push=True)
763
764 pts = [[x - w/2 + setback, y - h/2],
765 [x - w/2, y - h/2 + setback],
766 [x - w/2, y + h/2],
767 [x + w/2, y + h/2],
768 [x + w/2, y - h/2],
769 [x - w/2 + setback, y - h/2]]
770
771 self.Polyline(pts)
772
773 self.PopTransform()
774
775 def BoxWithOpenCorner(self, x, y, w, h,
776 setback=pcbnew.FromMM(1.27), flip=flipNone):
777 """!
778 Draw a box with an opening at the top left corner
779
780 @param x: the x coordinate of the circle's centre
781 @param y: the y coordinate of the circle's centre
782 @param w: the width of the box
783 @param h: the height of the box
784 @param setback: the set-back of the opening, in both x and y
785 @param flip: one of flipNone, flipX, flipY or flipBoth to change the
786 open corner position
787 """
788
789 self.TransformTranslate(x, y)
790 self.TransformFlipOrigin(flip)
791
792 pts = [[- w/2, - h/2 + setback],
793 [- w/2, + h/2],
794 [+ w/2, + h/2],
795 [+ w/2, - h/2],
796 [- w/2 + setback, - h/2]]
797
798 self.Polyline(pts)
799
800 self.PopTransform(num=2)
801
802 def RoundedBox(self, x, y, w, h, rad):
803 """!
804 Draw a box with rounded corners (i.e. a 90-degree circular arc)
805
806 :param x: the x coordinate of the box's centre
807 :param y: the y coordinate of the box's centre
808 :param w: the width of the box
809 :param h: the height of the box
810 :param rad: the radius of the corner rounds
811 """
812
813 x_inner = w - rad * 2
814 y_inner = h - rad * 2
815
816 x_left = x - w / 2
817 y_top = y - h / 2
818
819 # Draw straight sections
820 self.HLine(x_left + rad, y_top, x_inner)
821 self.HLine(x_left + rad, -y_top, x_inner)
822
823 self.VLine(x_left, y_top + rad, y_inner)
824 self.VLine(-x_left, y_top + rad, y_inner)
825
826 # corner arcs
827 ninety_deg = 90 * 10 # deci-degs
828 cx = x - w / 2 + rad
829 cy = y - h / 2 + rad
830
831 # top left
832 self.Arc(+cx, +cy, +x_left, +cy, +ninety_deg)
833 self.Arc(-cx, +cy, -x_left, +cy, -ninety_deg)
834 self.Arc(+cx, -cy, +x_left, -cy, -ninety_deg)
835 self.Arc(-cx, -cy, -x_left, -cy, +ninety_deg)
836
837 def ChamferedBox(self, x, y, w, h, chamfer_x, chamfer_y):
838 """!
839 Draw a box with chamfered corners.
840
841 :param x: the x coordinate of the box's centre
842 :param y: the y coordinate of the box's centre
843 :param w: the width of the box
844 :param h: the height of the box
845 :param chamfer_x: the size of the chamfer set-back in the x direction
846 :param chamfer_y: the size of the chamfer set-back in the y direction
847 """
848 # outermost dimensions
849 x_left = x - w / 2
850 y_top = y - h / 2
851
852 # x and y coordinates of inner edges of chamfers
853 x_inner = x_left + chamfer_x
854 y_inner = y_top + chamfer_y
855
856 pts = [
857 [+x_inner, +y_top],
858 [-x_inner, +y_top],
859 [-x_left, +y_inner],
860 [-x_left, -y_inner],
861 [-x_inner, -y_top],
862 [+x_inner, -y_top],
863 [+x_left, -y_inner],
864 [+x_left, +y_inner],
865 [+x_inner, +y_top],
866 ]
867
868 self.draw.Polyline(pts)
869
870 def MarkerArrow(self, x, y, direction=dirN, width=pcbnew.FromMM(1)):
871 """!
872 Draw a marker arrow facing in the given direction, with the
873 point at (x,y)
874
875 @param x: x position of the arrow tip
876 @param y: y position of the arrow tip
877 @param direction: arrow direction in degrees (0 is "north", can use
878 dir* shorthands)
879 @param width: arrow width
880 """
881
882 self.TransformTranslate(x, y)
883 self.TransformRotationOrigin(direction)
884
885 pts = [[0, 0],
886 [width / 2, width / 2],
887 [-width / 2, width / 2],
888 [0, 0]]
889
890 self.Polyline(pts)
891 self.PopTransform(2)
Collection of handy functions to simplify drawing shapes from within footprint wizards.
def SetLineTickness(self, lineThickness)
Old version of SetLineThickness.
def GetLayer(self)
Return the current drawing layer, used for drawing operations.
def BoxWithOpenCorner(self, x, y, w, h, setback=pcbnew.FromMM(1.27), flip=flipNone)
Draw a box with an opening at the top left corner.
def TransformPoint(self, x, y, mat=None)
Return a point (x, y) transformed by the given matrix, or if that is not given, the drawing context t...
def ChamferedBox(self, x, y, w, h, chamfer_x, chamfer_y)
Draw a box with chamfered corners.
def PushTransform(self, mat)
Add a transform to the top of the stack and recompute the overall transform.
def SetLayer(self, layer)
Set the current drawing layer, used for subsequent drawing operations.
def HLine(self, x, y, l)
Draw a horizontal line from (x,y), rightwards.
def TransformFlip(self, x, y, flip=flipNone, push=True)
Set up and return a transform matrix representing a horizontal, vertical or both flip about a point (...
def PopTransform(self, num=1)
Remove a transform from the top of the stack and recompute the overall transform.
def TransformRotation(self, x, y, rot, push=True)
Set up and return a transform matrix representing a rotation about the point (x,y),...
def NotchedCircle(self, x, y, r, notch_w, notch_h, rotate=0)
Circle radius r centred at (x, y) with a raised or depressed notch at the top Notch height is measure...
def SetLineThickness(self, lineThickness)
Set the current pen lineThickness used for subsequent drawing operations.
def Line(self, x1, y1, x2, y2)
Draw a line from (x1, y1) to (x2, y2)
def TransformTranslate(self, x, y, push=True)
Set up and return a transform matrix representing a translation optionally pushing onto the stack.
def NotchedBox(self, x, y, w, h, notchW, notchH, rotate=0)
Draw a box with a notch in the centre of the top edge.
def TransformFlipOrigin(self, flip, push=True)
Set up and return a transform matrix representing a horizontal, vertical or both flip about the origi...
def MarkerArrow(self, x, y, direction=dirN, width=pcbnew.FromMM(1))
Draw a marker arrow facing in the given direction, with the point at (x,y)
def TransformScaleOrigin(self, sx, sy=None, push=True)
Set up and return a transform matrix representing a scale about the origin, and optionally push onto ...
def Value(self, x, y, size, orientation_degree=0)
As for references, draw the module's value.
def Circle(self, x, y, r, filled=False)
Draw a circle at (x,y) of radius r If filled is true, the thickness and radius of the line will be se...
def RoundedBox(self, x, y, w, h, rad)
Draw a box with rounded corners (i.e.
def ResetTransform(self)
Reset the transform stack to the identity matrix.
def BoxWithDiagonalAtCorner(self, x, y, w, h, setback=pcbnew.FromMM(1.27), flip=flipNone)
Draw a box with a diagonal at the top left corner.
def TransformRotationOrigin(self, rot, push=True)
Set up and return a transform matrix representing a rotation about the origin, and optionally push on...
def Reference(self, x, y, size, orientation_degree=0)
Draw the module's reference as the given point.
def VLine(self, x, y, l)
Draw a vertical line from (x1,y1), downwards.
def Box(self, x, y, w, h)
Draw a rectangular box, centred at (x,y), with given width and height.
def RecomputeTransforms(self)
Re-compute the transform stack into a single transform and store in the DC.
def GetLineThickness(self)
Get the current drawing context line thickness.
def Polyline(self, pts, mirrorX=None, mirrorY=None)
Draw a polyline, optionally mirroring around the given points.
def Arc(self, cx, cy, sx, sy, angle)
Draw an arc based on centre, start and angle.
A class to simplify many aspects of footprint creation, leaving only the footprint specific routines ...
def GetTextThickness(self)
Thicker than IPC guidelines (10% of text height = 0.12mm) as 5 wires/mm is a common silk screen limit...
def GetTextSize(self)
Get the default text size for the footprint.
def CheckParameters(self)
Any custom parameter checking should be performed here.
def GetValue(self)
Return the value (name) of the generated footprint.
def BuildFootprint(self)
Actually make the footprint.
def SetModule3DModel(self)
If your plug-in sets a 3D model, override this function.
def BuildThisFootprint(self)
Draw the footprint.
def GetName(self)
Return the name of the footprint wizard.
def GetDescription(self)
Return the footprint wizard description.
def GenerateParameterList(self)
Footprint parameter specification is done here.
def FromMM(mm)
Definition: pcbnew.py:19754