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 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.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 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().SetPos0(self.TransformPoint(x, y))
640 self.module.Reference().SetPosition(
641 self.module.Reference().GetPos0())
642 self.module.Reference().SetTextSize(text_size)
643 self.module.Reference().SetTextAngle( pcbnew.EDA_ANGLE( orientation_degree, pcbnew.DEGREES_T ) )
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.VECTOR2I(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 self.module.Value().SetTextAngle( pcbnew.EDA_ANGLE( orientation_degree, pcbnew.DEGREES_T ) )
661
662 def Box(self, x, y, w, h):
663 """!
664 Draw a rectangular box, centred at (x,y), with given width and
665 height
666
667 @param x: the x coordinate of the box's centre
668 @param y: the y coordinate of the box's centre
669 @param w: the width of the box
670 @param h: the height of the box
671 """
672
673 pts = [[x - w/2, y - h/2], # left
674 [x + w/2, y - h/2], # right
675 [x + w/2, y + h/2], # bottom
676 [x - w/2, y + h/2], # top
677 [x - w/2, y - h/2]] # close
678
679 self.Polyline(pts)
680
681 def NotchedCircle(self, x, y, r, notch_w, notch_h, rotate=0):
682 """!
683 Circle radius r centred at (x, y) with a raised or depressed notch
684 at the top
685 Notch height is measured from the top of the circle radius
686
687 @param x: the x coordinate of the circle's centre
688 @param y: the y coordinate of the circle's centre
689 @param r: the radius of the circle
690 @param notch_w: the width of the notch
691 @param notch_h: the height of the notch
692 @param rotate: the rotation of the whole figure, in degrees
693 """
694
695 self.TransformRotation(x, y, rotate)
696
697 # find the angle where the notch vertical meets the circle
698 angle_intercept = math.asin(notch_w/(2 * r))
699
700 # and find the co-ords of this point
701 sx = math.sin(angle_intercept) * r
702 sy = -math.cos(angle_intercept) * r
703
704 # NOTE: this may be out by a factor of ten one day
705 arc_angle = (math.pi * 2 - angle_intercept * 2) * (1800/math.pi)
706
707 self.Arc(x, y, sx, sy, arc_angle)
708
709 pts = [[sx, sy],
710 [sx, -r - notch_h],
711 [-sx, -r - notch_h],
712 [-sx, sy]]
713
714 self.Polyline(pts)
715 self.PopTransform()
716
717 def NotchedBox(self, x, y, w, h, notchW, notchH, rotate=0):
718 """!
719 Draw a box with a notch in the centre of the top edge
720
721 @param x: the x coordinate of the circle's centre
722 @param y: the y coordinate of the circle's centre
723 @param w: the width of the box
724 @param h: the height of the box
725 @param notchW: the width of the notch
726 @param notchH: the height of the notch
727 @param rotate: the rotation of the whole figure, in degrees
728 """
729
730 self.TransformRotation(x, y, rotate)
731
732 # limit to half the overall width
733 notchW = min(x + w/2, notchW)
734
735 # draw notch
736 self.Polyline([ # three sides of box
737 (x - w/2, y - h/2),
738 (x - w/2, y + h/2),
739 (x + w/2, y + h/2),
740 (x + w/2, y - h/2),
741 # the notch
742 (notchW/2, y - h/2),
743 (notchW/2, y - h/2 + notchH),
744 (-notchW/2, y - h/2 + notchH),
745 (-notchW/2, y - h/2),
746 (x - w/2, y - h/2)
747 ])
748
749 self.PopTransform()
750
751 def BoxWithDiagonalAtCorner(self, x, y, w, h,
752 setback=pcbnew.FromMM(1.27), flip=flipNone):
753 """!
754 Draw a box with a diagonal at the top left corner.
755
756 @param x: the x coordinate of the circle's centre
757 @param y: the y coordinate of the circle's centre
758 @param w: the width of the box
759 @param h: the height of the box
760 @param setback: the set-back of the diagonal, in both x and y
761 @param flip: one of flipNone, flipX, flipY or flipBoth to change the
762 diagonal corner
763 """
764
765 self.TransformFlip(x, y, flip, push=True)
766
767 pts = [[x - w/2 + setback, y - h/2],
768 [x - w/2, y - h/2 + setback],
769 [x - w/2, y + h/2],
770 [x + w/2, y + h/2],
771 [x + w/2, y - h/2],
772 [x - w/2 + setback, y - h/2]]
773
774 self.Polyline(pts)
775
776 self.PopTransform()
777
778 def BoxWithOpenCorner(self, x, y, w, h,
779 setback=pcbnew.FromMM(1.27), flip=flipNone):
780 """!
781 Draw a box with an opening at the top left corner
782
783 @param x: the x coordinate of the circle's centre
784 @param y: the y coordinate of the circle's centre
785 @param w: the width of the box
786 @param h: the height of the box
787 @param setback: the set-back of the opening, in both x and y
788 @param flip: one of flipNone, flipX, flipY or flipBoth to change the
789 open corner position
790 """
791
792 self.TransformTranslate(x, y)
793 self.TransformFlipOrigin(flip)
794
795 pts = [[- w/2, - h/2 + setback],
796 [- w/2, + h/2],
797 [+ w/2, + h/2],
798 [+ w/2, - h/2],
799 [- w/2 + setback, - h/2]]
800
801 self.Polyline(pts)
802
803 self.PopTransform(num=2)
804
805 def RoundedBox(self, x, y, w, h, rad):
806 """!
807 Draw a box with rounded corners (i.e. a 90-degree circular arc)
808
809 :param x: the x coordinate of the box's centre
810 :param y: the y coordinate of the box's centre
811 :param w: the width of the box
812 :param h: the height of the box
813 :param rad: the radius of the corner rounds
814 """
815
816 x_inner = w - rad * 2
817 y_inner = h - rad * 2
818
819 x_left = x - w / 2
820 y_top = y - h / 2
821
822 # Draw straight sections
823 self.HLine(x_left + rad, y_top, x_inner)
824 self.HLine(x_left + rad, -y_top, x_inner)
825
826 self.VLine(x_left, y_top + rad, y_inner)
827 self.VLine(-x_left, y_top + rad, y_inner)
828
829 # corner arcs
830 ninety_deg = 90 * 10 # deci-degs
831 cx = x - w / 2 + rad
832 cy = y - h / 2 + rad
833
834 # top left
835 self.Arc(+cx, +cy, +x_left, +cy, +ninety_deg)
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
840 def ChamferedBox(self, x, y, w, h, chamfer_x, chamfer_y):
841 """!
842 Draw a box with chamfered corners.
843
844 :param x: the x coordinate of the box's centre
845 :param y: the y coordinate of the box's centre
846 :param w: the width of the box
847 :param h: the height of the box
848 :param chamfer_x: the size of the chamfer set-back in the x direction
849 :param chamfer_y: the size of the chamfer set-back in the y direction
850 """
851 # outermost dimensions
852 x_left = x - w / 2
853 y_top = y - h / 2
854
855 # x and y coordinates of inner edges of chamfers
856 x_inner = x_left + chamfer_x
857 y_inner = y_top + chamfer_y
858
859 pts = [
860 [+x_inner, +y_top],
861 [-x_inner, +y_top],
862 [-x_left, +y_inner],
863 [-x_left, -y_inner],
864 [-x_inner, -y_top],
865 [+x_inner, -y_top],
866 [+x_left, -y_inner],
867 [+x_left, +y_inner],
868 [+x_inner, +y_top],
869 ]
870
871 self.draw.Polyline(pts)
872
873 def MarkerArrow(self, x, y, direction=dirN, width=pcbnew.FromMM(1)):
874 """!
875 Draw a marker arrow facing in the given direction, with the
876 point at (x,y)
877
878 @param x: x position of the arrow tip
879 @param y: y position of the arrow tip
880 @param direction: arrow direction in degrees (0 is "north", can use
881 dir* shorthands)
882 @param width: arrow width
883 """
884
885 self.TransformTranslate(x, y)
886 self.TransformRotationOrigin(direction)
887
888 pts = [[0, 0],
889 [width / 2, width / 2],
890 [-width / 2, width / 2],
891 [0, 0]]
892
893 self.Polyline(pts)
894 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:19315