KiCad Pcbnew Python Scripting
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 wxPoint
437 """
438
439 if not mat:
440 mat = self.dc['transform']
441
442 return pcbnew.wxPoint(x * mat[0] + y * mat[1] + mat[2],
443 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 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.FP_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.FP_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.FP_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 _PolyLineInternal(pts) # original
607
608 if mirrorX is not None and mirrorY is not None:
609 self.TransformFlip(mirrorX, mirrorY, self.flipBoth) # both
610 _PolyLineInternal(pts)
611 self.PopTransform()
612
613 elif mirrorX is not None:
614 self.TransformFlip(mirrorX, 0, self.flipX)
615 _PolyLineInternal(pts)
616 self.PopTransform()
617
618 elif mirrorY is not None:
619 self.TransformFlip(0, mirrorY, self.flipY)
620 _PolyLineInternal(pts)
621 self.PopTransform()
622
623 def Reference(self, x, y, size, orientation_degree=0):
624 """!
625 Draw the module's reference as the given point.
626
627 The actual setting of the reference is not done in this drawing
628 aid - that is up to the wizard
629
630 @param x: the x position of the reference
631 @param y: the y position of the reference
632 @param size: the text size (in both directions)
633 @param orientation_degree: text orientation in degrees
634 """
635
636 text_size = pcbnew.wxSize(size, size)
637
638 self.module.Reference().SetPos0(self.TransformPoint(x, y))
639 self.module.Reference().SetPosition(
640 self.module.Reference().GetPos0())
641 self.module.Reference().SetTextSize(text_size)
642 # internal angles are in 0.1 deg
643 self.module.Reference().SetTextAngle(orientation_degree * 10)
644
645 def Value(self, x, y, size, orientation_degree=0):
646 """!
647 As for references, draw the module's value
648
649 @param x: the x position of the value
650 @param y: the y position of the value
651 @param size: the text size (in both directions)
652 @param orientation_degree: text orientation in degrees
653 """
654 text_size = pcbnew.wxSize(size, size)
655
656 self.module.Value().SetPos0(self.TransformPoint(x, y))
657 self.module.Value().SetPosition(self.module.Value().GetPos0())
658 self.module.Value().SetTextSize(text_size)
660 # internal angles are in 0.1 deg
661 self.module.Value().SetTextAngle(orientation_degree * 10)
662
663 def Box(self, x, y, w, h):
664 """!
665 Draw a rectangular box, centred at (x,y), with given width and
666 height
667
668 @param x: the x coordinate of the box's centre
669 @param y: the y coordinate of the box's centre
670 @param w: the width of the box
671 @param h: the height of the box
672 """
673
674 pts = [[x - w/2, y - h/2], # left
675 [x + w/2, y - h/2], # right
676 [x + w/2, y + h/2], # bottom
677 [x - w/2, y + h/2], # top
678 [x - w/2, y - h/2]] # close
679
680 self.Polyline(pts)
681
682 def NotchedCircle(self, x, y, r, notch_w, notch_h, rotate=0):
683 """!
684 Circle radius r centred at (x, y) with a raised or depressed notch
685 at the top
686 Notch height is measured from the top of the circle radius
687
688 @param x: the x coordinate of the circle's centre
689 @param y: the y coordinate of the circle's centre
690 @param r: the radius of the circle
691 @param notch_w: the width of the notch
692 @param notch_h: the height of the notch
693 @param rotate: the rotation of the whole figure, in degrees
694 """
695
696 self.TransformRotation(x, y, rotate)
697
698 # find the angle where the notch vertical meets the circle
699 angle_intercept = math.asin(notch_w/(2 * r))
700
701 # and find the co-ords of this point
702 sx = math.sin(angle_intercept) * r
703 sy = -math.cos(angle_intercept) * r
704
705 # NOTE: this may be out by a factor of ten one day
706 arc_angle = (math.pi * 2 - angle_intercept * 2) * (1800/math.pi)
707
708 self.Arc(x, y, sx, sy, arc_angle)
709
710 pts = [[sx, sy],
711 [sx, -r - notch_h],
712 [-sx, -r - notch_h],
713 [-sx, sy]]
714
715 self.Polyline(pts)
716 self.PopTransform()
717
718 def NotchedBox(self, x, y, w, h, notchW, notchH, rotate=0):
719 """!
720 Draw a box with a notch in the centre of the top edge
721
722 @param x: the x coordinate of the circle's centre
723 @param y: the y coordinate of the circle's centre
724 @param w: the width of the box
725 @param h: the height of the box
726 @param notchW: the width of the notch
727 @param notchH: the height of the notch
728 @param rotate: the rotation of the whole figure, in degrees
729 """
730
731 self.TransformRotation(x, y, rotate)
732
733 # limit to half the overall width
734 notchW = min(x + w/2, notchW)
735
736 # draw notch
737 self.Polyline([ # three sides of box
738 (x - w/2, y - h/2),
739 (x - w/2, y + h/2),
740 (x + w/2, y + h/2),
741 (x + w/2, y - h/2),
742 # the notch
743 (notchW/2, y - h/2),
744 (notchW/2, y - h/2 + notchH),
745 (-notchW/2, y - h/2 + notchH),
746 (-notchW/2, y - h/2),
747 (x - w/2, y - h/2)
748 ])
749
750 self.PopTransform()
751
752 def BoxWithDiagonalAtCorner(self, x, y, w, h,
753 setback=pcbnew.FromMM(1.27), flip=flipNone):
754 """!
755 Draw a box with a diagonal at the top left corner.
756
757 @param x: the x coordinate of the circle's centre
758 @param y: the y coordinate of the circle's centre
759 @param w: the width of the box
760 @param h: the height of the box
761 @param setback: the set-back of the diagonal, in both x and y
762 @param flip: one of flipNone, flipX, flipY or flipBoth to change the
763 diagonal corner
764 """
765
766 self.TransformFlip(x, y, flip, push=True)
767
768 pts = [[x - w/2 + setback, y - h/2],
769 [x - w/2, y - h/2 + setback],
770 [x - w/2, y + h/2],
771 [x + w/2, y + h/2],
772 [x + w/2, y - h/2],
773 [x - w/2 + setback, y - h/2]]
774
775 self.Polyline(pts)
776
777 self.PopTransform()
778
779 def BoxWithOpenCorner(self, x, y, w, h,
780 setback=pcbnew.FromMM(1.27), flip=flipNone):
781 """!
782 Draw a box with an opening at the top left corner
783
784 @param x: the x coordinate of the circle's centre
785 @param y: the y coordinate of the circle's centre
786 @param w: the width of the box
787 @param h: the height of the box
788 @param setback: the set-back of the opening, in both x and y
789 @param flip: one of flipNone, flipX, flipY or flipBoth to change the
790 open corner position
791 """
792
793 self.TransformTranslate(x, y)
794 self.TransformFlipOrigin(flip)
795
796 pts = [[- w/2, - h/2 + setback],
797 [- w/2, + h/2],
798 [+ w/2, + h/2],
799 [+ w/2, - h/2],
800 [- w/2 + setback, - h/2]]
801
802 self.Polyline(pts)
803
804 self.PopTransform(num=2)
805
806 def RoundedBox(self, x, y, w, h, rad):
807 """!
808 Draw a box with rounded corners (i.e. a 90-degree circular arc)
809
810 :param x: the x coordinate of the box's centre
811 :param y: the y coordinate of the box's centre
812 :param w: the width of the box
813 :param h: the height of the box
814 :param rad: the radius of the corner rounds
815 """
816
817 x_inner = w - rad * 2
818 y_inner = h - rad * 2
819
820 x_left = x - w / 2
821 y_top = y - h / 2
822
823 # Draw straight sections
824 self.HLine(x_left + rad, y_top, x_inner)
825 self.HLine(x_left + rad, -y_top, x_inner)
826
827 self.VLine(x_left, y_top + rad, y_inner)
828 self.VLine(-x_left, y_top + rad, y_inner)
829
830 # corner arcs
831 ninety_deg = 90 * 10 # deci-degs
832 cx = x - w / 2 + rad
833 cy = y - h / 2 + rad
834
835 # top left
836 self.Arc(+cx, +cy, +x_left, +cy, +ninety_deg)
837 self.Arc(-cx, +cy, -x_left, +cy, -ninety_deg)
838 self.Arc(+cx, -cy, +x_left, -cy, -ninety_deg)
839 self.Arc(-cx, -cy, -x_left, -cy, +ninety_deg)
840
841 def ChamferedBox(self, x, y, w, h, chamfer_x, chamfer_y):
842 """!
843 Draw a box with chamfered corners.
844
845 :param x: the x coordinate of the box's centre
846 :param y: the y coordinate of the box's centre
847 :param w: the width of the box
848 :param h: the height of the box
849 :param chamfer_x: the size of the chamfer set-back in the x direction
850 :param chamfer_y: the size of the chamfer set-back in the y direction
851 """
852 # outermost dimensions
853 x_left = x - w / 2
854 y_top = y - h / 2
855
856 # x and y coordinates of inner edges of chamfers
857 x_inner = x_left + chamfer_x
858 y_inner = y_top + chamfer_y
859
860 pts = [
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 [+x_inner, -y_top],
867 [+x_left, -y_inner],
868 [+x_left, +y_inner],
869 [+x_inner, +y_top],
870 ]
871
872 self.draw.Polyline(pts)
873
874 def MarkerArrow(self, x, y, direction=dirN, width=pcbnew.FromMM(1)):
875 """!
876 Draw a marker arrow facing in the given direction, with the
877 point at (x,y)
878
879 @param x: x position of the arrow tip
880 @param y: y position of the arrow tip
881 @param direction: arrow direction in degrees (0 is "north", can use
882 dir* shorthands)
883 @param width: arrow width
884 """
885
886 self.TransformTranslate(x, y)
887 self.TransformRotationOrigin(direction)
888
889 pts = [[0, 0],
890 [width / 2, width / 2],
891 [-width / 2, width / 2],
892 [0, 0]]
893
894 self.Polyline(pts)
895 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:18139