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