Dynamic landpatterns

#use-added-syntax(jitx)
defpackage dynamic_landpatterns:
  import core
  import jitx
  import jitx/commands
  import ocdb/utils/landpatterns
  import ocdb/utils/box-symbol

doc: \<DOC>
Static Version
<DOC>
pcb-landpattern Static_SOT23 :

  val x0 = 1.0  ; Lead-Span spacing
  val y0 = 0.95 ; Pitch
  ; Pad Definitions
  val pdef = smd-pad(0.8, 0.5)
  pad p[1] : pdef at loc((- x0), y0)
  pad p[2] : pdef at loc((- x0), (- y0))
  pad p[3] : pdef at loc(x0, 0.0)

  ; Non-Copper Geometry
  layer(Courtyard(Top)) = Rectangle(3.3, 3.0)
  layer(Silkscreen("f-silk", Top)) = LineRectangle(3.3, 3.0)
  ; Reference Designator Helper Function
  ref-label()

doc: \<DOC>
Very Limited Bounding Region Calculation
<DOC>
defn bounds (sh:Union|Shape) -> Rectangle :

  val extrema = to-tuple $ for s in shapes(sh as Union) seq:
    match(s):
      (r:Rectangle):
        val w2 = width(r) / 2.0
        val h2 = height(r) / 2.0
        ; println("W: %_ H: %_ P: %_" % [w2, h2, pose(r)] )
        [pose(r) * Point(w2, h2), pose(r) * Point((- w2), (- h2))]
      (other):
        throw $ Exception("Unhandled Shape")

  val max-x = maximum $ for obj in extrema map:
    x(obj[0])
  val max-y = maximum $ for obj in extrema map:
    y(obj[0])
  val min-x = minimum $ for obj in extrema map:
    x(obj[1])
  val min-y = minimum $ for obj in extrema map:
    y(obj[1])

  val mid-x = (max-x + min-x) / 2.0
  val mid-y = (max-y + min-y) / 2.0
  val w = max-x - min-x
  val h = max-y - min-y
  Rectangle(w, h, loc(mid-x, mid-y))

doc: \<DOC>
Dynamic Version
<DOC>
pcb-landpattern SOT-23 (pad-size:Dims, pad-grid:Dims, margin:Double = 0.2) :
  val x0 = x(pad-grid)
  val y0 = y(pad-grid)

  ; Pad Definitions
  val pdef = smd-pad(pad-size)
  pad p[1] : pdef at loc((- x0), y0)
  pad p[2] : pdef at loc((- x0), (- y0))
  pad p[3] : pdef at loc(x0, 0.0)

  ; Find the bounding box around all of the pads.
  val outline = bounds $ Union $ for pd in pads(self) seq:
    pose(pd) * pad-shape(pdef)

  ; Non-Copper Geometry
  val outline* = offset(outline, margin) as RoundedRectangle
  val courtyard = LineRectangle(width(outline*), height(outline*))
  layer(Courtyard(Top)) = courtyard
  layer(Silkscreen("f-silk", Top)) = courtyard

  val r = 0.15
  val marker = loc((width(outline*) / -2.0) - (3.0 * r), y0)
  layer(Silkscreen("f-silk", Top)) = marker * Circle(2.0 * r)
  ; Reference Designator Helper Function
  ref-label()


; view(Static_SOT23)
view(SOT-23(Dims(0.8, 0.5), Dims(1.0, 0.95)))