figures/asy/Circ.asy: Add the circuit library from my course project
authorW. Trevor King <wking@tremily.us>
Fri, 14 Jun 2013 11:22:53 +0000 (07:22 -0400)
committerW. Trevor King <wking@tremily.us>
Fri, 14 Jun 2013 11:23:51 +0000 (07:23 -0400)
For drawing a Peltier.

src/figures/asy/Circ-test.asy [new file with mode: 0644]
src/figures/asy/Circ.asy [new file with mode: 0644]

diff --git a/src/figures/asy/Circ-test.asy b/src/figures/asy/Circ-test.asy
new file mode 100644 (file)
index 0000000..b57a643
--- /dev/null
@@ -0,0 +1,137 @@
+/* Test suite for Circ.asy.
+ *
+ * Copyright (C) 2008-2012 W. Trevor King <wking@drexel.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+import Circ;
+
+real u = 2cm, v=0;
+
+write("resistor");
+MultiTerminal Rn = resistor(beg=(0,v), dir=0, type=normal,
+    label=Label("$R_{normal}$", align=N), value=Label("$30\ohm$", align=S));
+dot("beg", Rn.terminal[0], NW, red);
+dot("end", Rn.terminal[1], NE, red);
+dot("center", Rn.center, S, red);
+
+MultiTerminal Rvb = resistor(beg=(2u,v), dir=0, type=variable,
+    label=Label("$R_{variable}$", align=NW),
+    value=Label("$30\kohm$", align=SE));
+v -= u;
+
+write("capacitor");
+MultiTerminal Cn = capacitor((0,v), type=normal, "$C_{normal}$",
+    "30 $\mu$F");
+MultiTerminal Ce = capacitor((u,v), type=electrolytic, "$C_{electrolytic}$",
+    "30 $\mu$F");
+MultiTerminal Cvb = capacitor((2u,v), type=variable, "$C_{variable}$",
+    "30 $\mu$F");
+MultiTerminal Cvt = capacitor((3u,v), type=variant, "$C_{variant}$",
+    "30 $\mu$F");
+v -= u;
+
+write("inductor");
+MultiTerminal Lup = inductor((0,v), type=Up, "$L_{Up}$", "30 H");
+MultiTerminal Ldown = inductor((u,v), type=Down, "$L_{Down}$", "30 H");
+v -= u;
+
+write("diode");
+MultiTerminal Dn = diode((0,v), type=normal, "$D_{normal}$", "1.3 V");
+MultiTerminal Dz = diode((u,v), type=zener, "$D_{zener}$", "1.3 V");
+MultiTerminal Dled = diode((2u,v), type=LED, "$D_{LED}$", "1.7 V");
+v -= u;
+
+write("battery");
+MultiTerminal B = battery((0,v), "Battery", "1.5 V");
+v -= u;
+
+write("switch");
+MultiTerminal So = switchSPST((0,v), type=open, "$S$", "Open");
+MultiTerminal Sc = switchSPST((u,v), type=closed, "$S$", "Closed");
+MultiTerminal SPDT_o = switchSPDT((2u,v), type=open, "$S$", "Open");
+MultiTerminal SPDT_a = switchSPDT((3u,v), type=closed_a, "$S$", "Closed-A");
+MultiTerminal SPDT_b = switchSPDT((4u,v), type=closed_b, "$S$", "Closed-B");
+v -= u;
+
+write("current");
+MultiTerminal Icurr = current((0,v), "I", "10 A");
+v -= u;
+
+write("source");
+MultiTerminal Sdc = source((0,v), type=DC, "DC", "5 V");
+MultiTerminal Sac = source((u,v), type=AC, "AC", "5 V$_{pp}$");
+MultiTerminal Si = source((2u,v), type=I, "I", "5 A");
+MultiTerminal Sv = source((3u,v), type=V, "V", "5 V");
+v -= u;
+
+write("lamp");
+MultiTerminal Ln = lamp((0,v), 0, normal, "indicator", "5\ohm");
+MultiTerminal Li = lamp((u,v), 0, illuminating, "illuminator", "5\ohm");
+v -= 1.5u;
+
+write("positioning");
+MultiTerminal Spos = source((u,v), dir=90, type=DC, "DC", "5 V");
+MultiTerminal Rpos = resistor(type=normal,
+    label=rotate(90)*Label("+offset", align=W),
+    value=rotate(90)*Label("5 \ohm", align=E), draw=false);
+Rpos.centerto(Spos.terminal[0], Spos.terminal[1], offset=u);
+Rpos.draw();
+dot("Sa", Spos.terminal[0], S);
+dot("Sb", Spos.terminal[1], N);
+dot("Ra", Rpos.terminal[0], S);
+dot("Rb", Rpos.terminal[1], N);
+MultiTerminal Cpos = capacitor(type=normal, "-2offset", "4 F",draw=false);
+Cpos.centerto(Spos.terminal[0], Spos.terminal[1], offset=-2u);
+Cpos.draw();
+v -= u;
+
+write("wires");
+dot("nsq", (0,v), N);
+dot("b", (u/2,v-u/2), S);
+wire((0,v), (u/2,v-u/2), nsq);
+dot("udsq", (u,v), N);
+dot("b", (3u/2,v-u/2), S);
+wire((u,v), (3u/2,v-u/2), udsq);
+dot("rlsq", (2u,v), N);
+dot("b", (5u/2,v-u/2), S);
+wire((2u,v), (5u/2,v-u/2), rlsq);
+dot("udsq w/d", (3u,v), N);
+dot("b", (7u/2,v-u/2), S);
+wire((3u,v), (7u/2,v-u/2), udsq, -u/4);
+dot("rlsq w/d", (4u,v), N);
+dot("b", (9u/2,v-u/2), S);
+wire((4u,v), (9u/2,v-u/2), rlsq, u/4);
+v -= u;
+
+write("circuit");
+v -= u/2;  // this circuit takes up more height than the previous lines.
+MultiTerminal Ccirc = capacitor((0,v), dir=90);
+MultiTerminal Rcirc = resistor(draw=false);
+two_terminal_centerto(Ccirc, Rcirc);
+Rcirc.shift((u,0));  // gratuitous use of shift, but whatever...
+Rcirc.draw();
+// In the following, we assume the resistor is longer than the
+// capacitor.  If that is not true, you can find the corners of the
+// circuit programatically and use those corners.
+wire(Rcirc.terminal[1], Ccirc.terminal[1], rlsq);
+wire(Rcirc.terminal[0], Ccirc.terminal[0], rlsq);
+pair Pcirc[] = {
+  (Ccirc.terminal[0].x,Rcirc.terminal[0].y),
+  (Ccirc.terminal[1].x,Rcirc.terminal[1].y),
+  Rcirc.terminal[1], Rcirc.terminal[0]};
+kirchhoff_loop(Pcirc);
+v -= u;
diff --git a/src/figures/asy/Circ.asy b/src/figures/asy/Circ.asy
new file mode 100644 (file)
index 0000000..9d202bb
--- /dev/null
@@ -0,0 +1,1084 @@
+/* Useful functions for drawing circuit diagrams.
+ * Version 0.2
+ *
+ * Copyright (C) 2003 GS Bustamante Argañaraz
+ *               2008-2012 W. Trevor King <wking@drexel.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *
+ * Based on MetaPost's MakeCirc by Gustavo Sebastian Bustamante Argañaraz.
+ *   http://www.ctan.org/tex-archive/help/Catalogue/entries/makecirc.html
+ */
+
+// Command definitions for easier labeling
+
+texpreamble("\def\ohm{\ensuremath{\,\Omega}}");
+texpreamble("\def\kohm{\,k\ensuremath{\Omega}}");
+texpreamble("\def\modarg#1#2{\setbox0=\hbox{$\mkern-1mu/#2^\circ$}\dp0=.21ex $#1\underline{\box0}$}");
+
+int rotatelabel = 0;
+int norotatelabel = 1;
+int labeling = rotatelabel;
+
+// Macros for the pens, I define them as such so when they expand,
+// look for the last value assigned to linewd and use it
+// (thanks to JLD). The linewd value assigns it as newinternal to
+// be able to change it «from out».
+
+real linewd = 0.25mm;
+
+pen line = linewidth(linewd);
+pen misc = linewidth(0.8*linewd);
+pen kirchhoff_pen = linewidth(10*linewd)+gray(0.7);
+
+// Arrowhead definitions
+
+real ahlength = 4bp; // Arrowhead length
+real ahangle = 30;   // Arrowhead angle
+
+path miscahead (path p)
+{
+  real t = reltime(p, 1.0);
+  pair A = point(p,t);
+  pair u = -dir(p,t);
+  path a = shift(A)*((0,0)--(scale(ahlength)*rotate(15)*u));
+  path b = shift(A)*((0,0)--(scale(ahlength)*rotate(-15)*u));
+  return (a & reverse(a) & b & reverse(b))--cycle;
+}
+
+path fullhead (path p, real length=ahlength, real angle=ahangle)
+{
+  real t = reltime(p, 1.0);
+  pair A = point(p,t);
+  pair u = -dir(p,t);
+  path a = shift(A)*((0,0)--(scale(length)*rotate(angle/2)*u));
+  path b = shift(A)*((0,0)--(scale(length)*rotate(-angle/2)*u));
+  return (A -- a -- reverse(b) --cycle);
+}
+
+path bjtahead (path p)
+{
+  pair A = point(p,reltime(p,0.7));
+  pair u = -dir(p,reltime(p,0.5));
+  path a = shift(A)*((0,0)--(scale(ahlength)*rotate(20)*u));
+  path b = shift(A)*((0,0)--(scale(ahlength)*rotate(-20)*u));
+  return (a & reverse(a) & b & reverse(b))--cycle;
+}
+
+// function to wire the symbols together
+
+int nsq=0, udsq=2, rlsq=3;
+
+void wire(pair pin_beg, pair pin_end, int type=nsq, real dist=0)
+{
+  if (dist == 0) {
+    if (type==nsq) {
+      draw(pin_beg--pin_end, line);
+    } else if (type==udsq) {
+      draw(pin_beg--(pin_beg.x,pin_end.y)--pin_end, line);
+    } else if (type==rlsq) {
+      draw(pin_beg--(pin_end.x,pin_beg.y)--pin_end, line);
+    } else {
+      write("Error, unrecognized wire type ",type);
+    }
+  } else {
+    if (type==udsq) {
+      draw(pin_beg--(pin_beg+(0,dist))--(pin_end.x,pin_beg.y + dist)
+           --pin_end, line);
+    } else if (type==rlsq) {
+      draw(pin_beg--(pin_beg+(dist,0))--(pin_beg.x + dist,pin_end.y)
+           --pin_end, line);
+    } else {
+      write("Error, unrecognized wire type ",type);
+    }
+  }
+}
+
+// ----- Here the symbols begin --------
+
+transform _shift_transform(pair z) = shift;
+
+struct MultiTerminal {
+  pair center;
+  real dir;
+  pair terminal[];
+  pair terminal_offset[];
+  Label label;
+  Label value;
+  real label_offset;
+  real value_offset;
+  path pLine[]; // cyclic paths are filled in
+  path pMisc[];
+  pen line;
+  pen misc;
+
+  void set_terminals() {
+    for (int i=0; i < this.terminal_offset.length; i+=1) {
+      this.terminal[i] = this.center +
+          rotate(this.dir)*this.terminal_offset[i];
+    }
+  }
+
+  void operator init(pair center=(0,0), real dir=0,
+                     pair terminal[]={}, pair terminal_offset[]={},
+                     Label label="", Label value="",
+                     real label_offset=0, real value_offset=0,
+                     path pLine[]={}, path pMisc[]={},
+                     pen line=line, pen misc=misc) {
+    this.center = center;
+    this.dir = dir % 360;
+    this.terminal = terminal;
+    this.terminal_offset = terminal_offset;
+    this.set_terminals();
+    this.label = label;
+    this.value = value;
+    this.label_offset = label_offset;
+    this.value_offset = value_offset;
+    this.pLine = pLine;
+    this.pMisc = pMisc;
+    this.line = line;
+    this.misc = misc;
+  }
+
+  /* Shift position by a */
+  void shift(pair a) {
+    this.center += a;
+    this.set_terminals();
+  }
+
+  void draw_label(picture pic=currentpicture, Label L=null, real offset=0,
+                  pair default_direction=(0,0)) {
+    align a;
+    if (L == null) {
+      L = this.label;
+    }
+    a = L.align;
+    if ((L.align == NoAlign || L.align.dir == (0,0)) &&
+        default_direction != (0,0)) {
+      L.align = rotate(this.dir)*default_direction;
+    }
+    if (L.align != NoAlign && L.align != Align) {
+      real m = labelmargin(L.p);
+      real scale = (m + offset)/m;
+      if (L.align.is3D) {
+        L.align.dir3 *= scale;
+      } else {
+        L.align.dir *= scale;
+      }
+    }
+    label(pic=pic, L=L, position=this.center);
+    L.align = a;
+  }
+
+  /* Rather than placing the element with a point and direction (mid,
+   * dir), center an element between the pairs a and b.  The optional
+   * offset shifts the element in the direction rotated(90)*(b-a)
+   * (i.e. up for offset > 0 if b is directly right of a).
+   */
+  void centerto(pair a, pair b, real offset=0) {
+    this.dir = degrees(b-a);
+    this.center = (a+b)/2 + offset*dir(this.dir+90);
+    this.set_terminals();
+  }
+
+  void draw(picture pic=currentpicture) {
+    for (int i=0; i< pLine.length; i+=1) {
+      path p = _shift_transform(this.center)*rotate(this.dir)*pLine[i];
+      if (cyclic(p))
+        filldraw(pic, p, this.line, this.line);
+      else
+        draw(pic, p, this.line);
+    }
+    for (int i=0; i< pMisc.length; i+=1) {
+      path p = _shift_transform(this.center)*rotate(this.dir)*pMisc[i];
+      if (cyclic(p))
+        filldraw(pic, p, this.misc, this.misc);
+      else
+        draw(pic, p, this.misc);
+    }
+    this.draw_label(pic=pic, L=this.label, offset=this.label_offset,
+        default_direction=N);
+    this.draw_label(pic=pic, L=this.value, offset=this.value_offset,
+        default_direction=S);
+  }
+}
+
+pair _offset(pair beg=(0,0), real length=1, real dir=0) {
+  return beg + rotate(dir)*(length, 0);
+}
+
+void two_terminal_centerto(MultiTerminal reference, MultiTerminal target,
+                           real offset=0, bool reverse=false)
+{
+  if (reverse == false)
+    target.centerto(reference.terminal[0], reference.terminal[1], offset);
+  else
+    target.centerto(reference.terminal[1], reference.terminal[0], offset);
+}
+
+// --- Resistor (Resistencia) ---
+
+real rstlth=2mm;
+int normal=0, variable=2;
+
+MultiTerminal resistor(pair beg=(0,0), real dir=0, int type=normal,
+                       Label label="", Label value="", bool draw=true)
+{
+  path pLine, pLines[]={}, pMisc[]={};
+  real len = 7rstlth;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=len/2, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  pLine = (-len/2,0)--(-1.5rstlth,0)--(-1.25rstlth,.75rstlth);
+  for (real i=.5; i<=2.5; i+=0.5)
+    pLine = pLine--((-1.25+i)*rstlth,((-1)**(2i))*.75rstlth);
+  pLine = pLine -- (1.5rstlth,0)--(len/2,0);
+  if (type==normal) {
+    ; //pass
+  } else if (type==variable) {
+    ahlength=.8rstlth;
+    pMisc.push((-1.5rstlth,-rstlth)--(1.5rstlth,rstlth));
+    pMisc.push(miscahead((-1.5rstlth,-rstlth)--(1.5rstlth,rstlth)));
+  } else {
+    write("Error, unrecognized resistor type ",type);
+  }
+  pLines.push(pLine);
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=.8rstlth, value_offset=.8rstlth,
+      pLine=pLines, pMisc=pMisc);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+// --- Inductor (bobina) ---
+
+real coil=2mm;
+int Up=0, Down=1;
+
+MultiTerminal inductor(pair beg=(0,0), real dir=0, int type=Up,
+                       Label label="", Label value="", bool draw=true)
+{
+  path pLine;
+  real len = 6coil;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=len/2, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  pLine = (-len/2,0) -- (-2coil,0);
+
+  if (type==Up) {
+    for (int i=-1; i<=2; i+=1)
+      pLine = pLine{N}..{S}(i*coil,0);
+  } else if (type==Down) {
+    for (int i=-1; i<=2; i+=1)
+      pLine = pLine{S}..{N}(i*coil,0);
+  } else {
+    write("Error, unrecognized inductor type ",type);
+  }
+  pLine = pLine -- (len/2,0);
+
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=.8rstlth, value_offset=.8rstlth,
+      pLine=pLine);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+// --- Capacitor (condensador) ---
+
+real platsep=1mm;
+int normal=0, electrolytic=1, variable=2, variant=3;
+
+MultiTerminal capacitor(pair beg=(0,0), real dir=0, int type=normal,
+                        Label label="", Label value="", bool draw=true)
+{
+  path pLine[]={}, pMisc[]={};
+  real len = 7platsep;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=len/2, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  pLine.push((-len/2,0)--(-platsep/2,0));
+  pLine.push((platsep/2,0)--(len/2,0));
+
+  if (type==normal) {
+    pLine.push((-platsep/2,-2.5platsep)--(-platsep/2,2.5platsep));
+    pLine.push((platsep/2,-2.5platsep)--(platsep/2,2.5platsep));
+  } else if (type==electrolytic) {
+    pLine.push((-platsep/2,-1.8platsep)--(-platsep/2,1.8platsep));
+    pLine.push((-1.5platsep,-2.5platsep)--(platsep/2,-2.5platsep)
+               --(platsep/2,+2.5platsep)--(-1.5platsep,2.5platsep));
+  } else if (type==variable) {
+    pLine.push((-platsep/2,-2.5platsep)--(-platsep/2,2.5platsep));
+    pLine.push((platsep/2,-2.5platsep)--(platsep/2,2.5platsep));
+    pMisc.push((-2.5platsep,-2.5platsep)--(2.5platsep,2.5platsep));
+    ahlength=1.7platsep;
+    pMisc.push(miscahead((-2.5platsep,-2.5platsep)--(2.5platsep,2.5platsep)));
+  } else if (type==variant) {
+    pLine.push((-platsep/2,-2.5platsep)--(-platsep/2,2.5platsep));
+    pLine.push((platsep,-2.5platsep)..(platsep/2,0)..(platsep,2.5platsep));
+  } else {
+    write("Error, unrecognized capacitor type ",type);
+  }
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=2.5platsep,
+      value_offset=2.5platsep, pLine=pLine, pMisc=pMisc);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+// --- Diode (diodo) ---
+
+real diode_height = 3.5mm;
+int zener=1, LED=2;
+// I droped the pin parameters, since other device (e.g. electrolytic
+// capacitors) are also polarized.  The positioning method centerto(),
+// provides enough flexibility.
+
+MultiTerminal diode(pair beg=(0,0), real dir=0, int type=normal,
+                    Label label="", Label value="", bool draw=true)
+{
+  path pLine[]={}, pMisc[]={};
+  real len = 3*diode_height;
+  real r = diode_height/2;
+  real label_offset, value_offset;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=len/2, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  label_offset = value_offset = r;
+  pLine.push((-len/2,0)--(-r,0)--(-r,r)--(r,0)--(-r,-r)--(-r,0));
+  pLine.push((r,0)--(len/2,0));
+
+  if (type==normal) {
+    pLine.push((r,-r)--(r,r));
+  } else if (type==zener) {
+    pLine.push((2r,-r)--(r,-r)--(r,r)--(0,r));
+  } else if (type==LED) {
+    path a = (-r,r)--(r,0);
+    pair u = unit((0.5, 1)); // perpendicular to a
+    path b = (0,0)--diode_height*u;
+    pLine.push((r,-r)--(r,r));
+    label_offset = 1.5*diode_height;
+    pMisc.push(shift(point(a,reltime(a,0.25))+point(b,0.33))*((0,0)--diode_height*u));
+    pMisc.push(shift(point(a,reltime(a,0.60))+point(b,0.33))*((0,0)--diode_height*u));
+    pMisc.push(fullhead(pMisc[0], 0.4*diode_height, 30));
+    pMisc.push(fullhead(pMisc[1], 0.4*diode_height, 30));
+  } else {
+    write("Error, unrecognized diode type ",type);
+  }
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=label_offset,
+      value_offset=value_offset, pLine=pLine, pMisc=pMisc);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+//--- Battery (bater'ia) ---
+
+real battery_size = 6mm;
+
+MultiTerminal battery(pair beg=(0,0), real dir=0,
+                      Label label="", Label value="", bool draw=true)
+{
+  path pLine[]={}, pMisc[]={};
+  real len = 1.8*battery_size;
+  real r = battery_size/2;
+  real x = 0.4*battery_size;
+  real Y = 0.6*battery_size;
+  real y = 0.2*battery_size;
+  real label_offset, value_offset;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=len/2, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  label_offset = value_offset = Y;
+  pLine.push((-len/2,0)--(-r,0));
+  pLine.push((r,0)--(len/2,0));
+  for (int i=0; i<3; i+=1) {
+    pLine.push((-r+x*i, -y)--(-r+x*i, y));
+    pLine.push((-r+x*(i+0.5), -Y)--(-r+x*(i+0.5), Y));
+  }
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=label_offset,
+      value_offset=value_offset, pLine=pLine, pMisc=pMisc);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+//--- Switches (Llaves) ---
+
+int open=0, closed=1;
+real switch_size = 3mm;
+
+/* Helper function for constructing switch paths. */
+path[] _switch_lines(pair terminal_offset[], real theta)
+{
+  path pLine[] = {};
+  real r = switch_size/2;
+  real dy = switch_size/6;  // little nub where the switch closes
+  pLine.push((-r,0)--((-r,0)+switch_size*dir(theta)));
+  for (int i=0; i < terminal_offset.length; i+=1) {
+    pLine.push(shift(terminal_offset[i])*scale(dy)*unitcircle);
+  }
+  return pLine;
+}
+
+/* `switch' is a Asymptote keyword (or it should be), so append SPST
+ * for Single Pole Single Throw.
+ */
+MultiTerminal switchSPST(pair beg=(0,0), real dir=0, int type=open,
+                         Label label="", Label value="", bool draw=true)
+{
+  path pLine[] = {};
+  real theta, label_offset, value_offset;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=switch_size/2, dir=dir);
+  pair terminal_offset[] = {
+      (-switch_size/2, 0),
+      (switch_size/2, 0)};
+
+  value_offset = 0;
+  if (type==open) {
+    theta = 35;
+  } else if (type==closed) {
+    theta = 10;
+  } else {
+    write("Error, unrecognized switchSPST type ",type);
+  }
+  pLine = _switch_lines(terminal_offset=terminal_offset, theta=theta);
+  label_offset = switch_size*Sin(theta);
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=label_offset,
+      value_offset=value_offset, pLine=pLine);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+int closed_a=1, closed_b=2;
+
+/* A Single Pole Double Throw switch. */
+MultiTerminal switchSPDT(pair beg=(0,0), real dir=0, int type=open,
+                         Label label="", Label value="", bool draw=true)
+{
+  path pLine[] = {};
+  real theta, label_offset, value_offset;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=switch_size/2, dir=dir);
+  pair terminal_offset[] = {
+      (-switch_size/2, 0),
+      (switch_size*sqrt(3)/4, switch_size/2),
+      (switch_size*sqrt(3)/4, -switch_size/2)};
+
+  label_offset = value_offset = switch_size/2;
+  if (type==open) {
+    theta = 0;
+  } else if (type==closed_a) {
+    theta = 20;
+  } else if (type==closed_b) {
+    theta = -20;
+  } else {
+    write("Error, unrecognized switchSPST type ",type);
+  }
+  pLine = _switch_lines(terminal_offset=terminal_offset, theta=theta);
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=label_offset,
+      value_offset=value_offset, pLine=pLine);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+//--- Current (Corriente) ---
+
+real current_size = 2mm;
+
+MultiTerminal current(pair beg=(0,0), real dir=0,
+                      Label label="", Label value="", bool draw=true)
+{
+  path pLine[]={}, pMisc[]={};
+  real label_offset, value_offset;
+  real len = 2*current_size;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=len/2, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  label_offset = value_offset = 0.4*current_size;
+  pLine.push((-len/2, 0) -- (current_size/2, 0));
+  pLine.push((current_size/2, 0) -- (len/2, 0));
+  pMisc.push(fullhead(pLine[0], current_size, 45));
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=label_offset,
+      value_offset=value_offset, pLine=pLine, pMisc=pMisc);
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+//--- Circle-based symbols (for internal use) --
+
+real circle_size = 6mm;
+
+MultiTerminal _circle_symbol(pair beg=(0,0), real dir=0,
+                             Label label="", Label value="")
+{
+  path pLine[]={};
+  real label_offset, value_offset;
+  real len = 2*circle_size;
+  real r = circle_size/2;
+  MultiTerminal term;
+  pair center = _offset(beg=beg, length=r, dir=dir);
+  pair terminal_offset[] = {
+      (-len/2, 0),
+      (len/2, 0)};
+
+  label_offset = value_offset = r;
+  pLine.push((-len/2, 0) -- (-r, 0));
+  pLine.push((r, 0) -- (len/2, 0));
+  pLine.push(scale(r)*(E..N..W..S..E));
+  term = MultiTerminal(center=center, dir=dir, terminal_offset=terminal_offset,
+      label=label, value=value, label_offset=label_offset,
+      value_offset=value_offset, pLine=pLine);
+  return term;
+}
+
+//--- Sources (fuentes de alimentaci'on) ---
+
+int AC=0,DC=1,I=2,V=3;
+
+MultiTerminal source(pair beg=(0,0), real dir=0, int type=AC,
+                     Label label="", Label value="", bool draw=true)
+{
+  MultiTerminal term;
+
+  if (type == AC || type == I || type == V) {
+    real r = circle_size/2;
+    term = _circle_symbol(beg=beg, dir=dir, label=label, value=value);
+    if (type == AC) {
+      term.pLine.push((-2r/3,0){NE}..{E}(-r/3,.4r)..{SE}(0,0)..{E}(r/3,-.4r)..{NE}(2r/3,0));
+    } else if (type == I) {
+      term.pLine.push((-2r/3,0)--(2r/3,0));
+      term.pLine.push(fullhead(term.pLine[3], 8r/15, 30));
+    } else if (type == V) {
+      term.pLine.push((-0.9r,0)--(-0.1r,0));
+      term.pLine.push((0.5r,-.4r)--(0.5r,.4r));
+      term.pLine.push((0.1r,0)--(0.9r,0));
+    }
+  } else if (type == DC) {
+    path pLine[]={};
+    real label_offset, value_offset;
+    real len = battery_size;
+    real x = 0.2*battery_size;
+    real Y = 0.6*battery_size;
+    real y = 0.2*battery_size;
+    pair center = _offset(beg=beg, length=len/2, dir=dir);
+    pair terminal_offset[] = {
+        (-len/2, 0),
+        (len/2, 0)};
+
+    label_offset = value_offset = Y;
+    pLine.push((-len/2,0)--(-x/2,0));
+    pLine.push((x/2,0)--(len/2,0));
+    pLine.push((-x/2, -y)--(-x/2, y));
+    pLine.push((x/2, -Y)--(x/2, Y));
+    term = MultiTerminal(center=center, dir=dir,
+        terminal_offset=terminal_offset,
+        label=label, value=value, label_offset=label_offset,
+        value_offset=value_offset, pLine=pLine);
+  }
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+/*
+
+//%%<--- Transistor --->%%%
+newinternal npn, pnp, cnpn, cpnp, bjtlth;
+npn=1; pnp=-1; cnpn=0; cpnp=2; bjtlth=7mm;
+
+vardef transistor@#(expr z,type,ang)=
+       save BJT;
+       pair T@#.B,T@#.E,T@#.C; % pines: Base, Emisor, Colector %
+       T@#.B=z;
+       T@#.E=(z+(bjtlth,-.75bjtlth)) rotatedaround(z,ang);
+       T@#.C=(z+(bjtlth,.75bjtlth)) rotatedaround(z,ang);
+       picture BJT;
+       BJT=nullpicture;
+       
+       addto BJT doublepath z--(z+(.5bjtlth,0)) withpen line;
+       addto BJT doublepath (z+(.5bjtlth,-.5bjtlth))--(z+(.5bjtlth,.5bjtlth)) withpen line;
+       addto BJT doublepath (z+(.5bjtlth,.2bjtlth))--(z+(bjtlth,.5bjtlth))
+       --(z+(bjtlth,.75bjtlth)) withpen line;
+       
+       if type=npn:
+               addto BJT doublepath (z+(.5bjtlth,-.2bjtlth))--(z+(bjtlth,-.5bjtlth))
+               --(z+(bjtlth,-.75bjtlth)) withpen line;
+               addto BJT contour bjtahead (z+(.5bjtlth,-.2bjtlth))
+               --(z+(bjtlth,-.5bjtlth)) withpen line;
+       elseif type=cnpn:
+               addto BJT doublepath (z+(.5bjtlth,-.2bjtlth))--(z+(bjtlth,-.5bjtlth))
+               --(z+(bjtlth,-.75bjtlth)) withpen line;
+               addto BJT contour bjtahead (z+(.5bjtlth,-.2bjtlth))
+               --(z+(bjtlth,-.5bjtlth)) withpen line;
+               addto BJT doublepath fullcircle scaled 1.3bjtlth shifted (z+(.65bjtlth,0))
+                withpen line;
+       elseif type=pnp:
+               addto BJT doublepath (z+(bjtlth,-.75bjtlth))--(z+(bjtlth,-.5bjtlth))
+               --(z+(.5bjtlth,-.2bjtlth)) withpen line;
+               addto BJT contour bjtahead (z+(bjtlth,-.5bjtlth))
+               --(z+(.5bjtlth,-.2bjtlth)) withpen line;
+       elseif type=cpnp:
+               addto BJT doublepath (z+(bjtlth,-.75bjtlth))--(z+(bjtlth,-.5bjtlth))
+               --(z+(.5bjtlth,-.2bjtlth)) withpen line;
+               addto BJT contour bjtahead (z+(bjtlth,-.5bjtlth))
+               --(z+(.5bjtlth,-.2bjtlth)) withpen line;
+               addto BJT doublepath fullcircle scaled 1.3bjtlth shifted (z+(.65bjtlth,0)) withpen line;
+       fi;
+       
+       draw BJT rotatedaround(z,ang);
+enddef;
+
+//%%<--- Measurement instruments (Intrumentos de medicion)--->%%%
+newinternal volt, ampere, watt;
+volt=0; ampere=1; watt=2;
+
+vardef meains@#(expr z,type,ang,name)=
+       save meter;
+       pair mi@#.l, mi@#.r, mi@#.p; % pines %
+       mi@#.l=z; mi@#.r=(z+(2ssize,0)) rotatedaround(z,ang);
+       
+       picture meter; meter=nullpicture;
+       addto meter doublepath z--(z+(.5ssize,0));
+       addto meter doublepath (z+(1.5ssize,0))--(z+(2ssize,0));
+       if (type=volt) || (type=ampere):        
+               addto meter doublepath fullcircle scaled ssize shifted (z+(ssize,0));
+               if type=volt:
+                       addto meter also thelabel(latex("\textsf{V}") scaled (ssize/6mm) 
+                       rotated (-ang), (z+(ssize,0)));
+               elseif type=ampere:
+                       addto meter also thelabel(latex("\textsf{A}") scaled (ssize/6mm) 
+                       rotated (-ang), (z+(ssize,0)));
+               fi;
+       elseif (type=watt):
+               mi@#.p=(z+(ssize,-ssize)) rotatedaround(z,ang);
+               addto meter doublepath (z+(.5ssize,-.5ssize))--(z+(.5ssize,.5ssize))
+               --(z+(1.5ssize,.5ssize))--(z+(1.5ssize,-.5ssize))--cycle;
+               addto meter doublepath (z+(ssize,-.5ssize))--(z+(ssize,-ssize));
+               addto meter also thelabel(latex("\textsf{W}") scaled (ssize/6mm) 
+               rotated (-ang), (z+(ssize,0)));
+       fi;
+       
+       draw meter rotatedaround(z,ang) withpen line;
+       
+       if labeling=rotatelabel:
+               if ((ang > (-90)) && (ang <= 90)) || ((ang > 270) && (ang <= 450)):
+                       label(latex(name) rotatedaround (.5[mi@#.l,mi@#.r],ang), 
+                       (.5ssize+lbsep)*dir (90+ang) shifted .5[mi@#.l,mi@#.r]);
+               elseif ((ang > 90) && (ang <= 270)) || ((ang > (-270)) && (ang <= (-90))):
+                       label(latex(name) rotatedaround (.5[mi@#.l,mi@#.r],180+ang), 
+                       (.5ssize+lbsep)*dir (90+ang) shifted .5[mi@#.l,mi@#.r]);
+               fi;
+       elseif labeling=norotatelabel:
+               if (ang = 0):
+                       label.top(latex(name), (.5ssize+.25lbsep)*dir (90+ang) 
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif (ang > 0) && (ang < 90):
+                       label.ulft(latex(name), (.5ssize)*dir (90+ang) 
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif (ang = 90):
+                       label.lft(latex(name),(.5ssize+.25lbsep)*dir (90+ang)
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif (90 < ang) && (ang < 180):
+                       label.llft(latex(name),(.5ssize)*dir (90+ang)
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif (ang = 180) || (ang = (-180)):
+                       label.bot(latex(name), (.5ssize+.25lbsep)*dir (90+ang) 
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif ((ang > 180) && (ang < 270)) || ((ang > (-180)) && (ang < (-90))):
+                       label.lrt(latex(name),(.5ssize)*dir (90+ang)
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif (ang = 270) || (ang = (-90)):
+                       label.rt(latex(name), (.5ssize+.25lbsep)*dir (90+ang) 
+                       shifted .5[mi@#.l,mi@#.r]);
+               elseif ((270 < ang) && (ang < 360)) || ((ang < 0) && (ang > (-90))):
+                       label.urt(latex(name),(.5ssize)*dir (90+ang)
+                       shifted .5[mi@#.l,mi@#.r]);
+               fi;
+       fi;
+enddef;
+
+// --- Electrical machines (maquinas electricas) ---
+
+TwoTerminal motor(pair beg, real ang, string name, string val)
+{
+  path pLine;
+  TwoTerminal term;
+
+  if (type==Up) {
+    pLine = (0,0)--(coil,0);
+    for (int i=2; i<=4; i+=1)
+      pLine = pLine{N}..{S}(i*coil,0);
+    pLine = pLine{N}..{S}(5coil,0)--(6coil,0);
+  } else if (type==Down) {
+    pLine = (0,0)--(coil,0);
+    for (int i=2; i<=4; i+=1)
+      pLine = pLine{S}..{N}(i*coil,0);
+    pLine = pLine{S}..{N}(5coil,0)--(6coil,0);
+    // original makecirc changed labelangle to ang-180
+  }
+  term = TwoTerminal(beg, 6coil, ang, coil, coil, name, val, pLine);
+  // original makecirc used .5coil for lcharv
+  term.draw();
+  return term;
+}
+       M@#.D=z; M@#.B=(z+(2ssize,0)) rotatedaround(z,ang);
+       picture mot; mot=nullpicture;
+       
+       addto mot doublepath z--(z+(.4ssize,0));
+       addto mot doublepath (z+(1.6ssize,0))--(z+(2ssize,0));
+       addto mot doublepath fullcircle scaled ssize shifted (z+(ssize,0));
+       addto mot also thelabel(latex("\textsf{M}") scaled (ssize/6mm) 
+       rotated (-ang), (z+(ssize,0)));
+       
+       path p,q,r,s,ca,cb,c,hc;
+       p=(z+(.6ssize,.075ssize))--(z+(.4ssize,.075ssize));
+       q=(z+(.4ssize,.075ssize))--(z+(.4ssize,-.075ssize));
+       ca=(z+(.4ssize,-.075ssize))--(z+(.6ssize,-.075ssize));
+       
+       
+       r=(z+(1.4ssize,.075ssize))--(z+(1.6ssize,.075ssize));
+       s=(z+(1.6ssize,.075ssize))--(z+(1.6ssize,-.075ssize));
+       cb=(z+(1.6ssize,-.075ssize))--(z+(1.4ssize,-.075ssize));
+       
+       c=fullcircle scaled ssize shifted (z+(ssize,0));
+       hc=halfcircle scaled ssize rotated 270 shifted (z+(ssize,0));
+       
+       addto mot contour buildcycle(p,q,ca,c);
+       addto mot doublepath buildcycle(p,q,ca,c);
+       
+       addto mot contour buildcycle(cb,s,r,hc);
+       addto mot doublepath buildcycle(cb,s,r,hc);
+       
+       draw mot rotatedaround(z,ang) withpen line;
+       
+       putlabel(M@#.D,M@#.B,.5ssize,.5ssize,ang,name,val);
+enddef;
+
+vardef generator@#(expr z,ang,name,val)=
+       save gen;
+       pair G@#.D, G@#.B; % pines %
+       G@#.D=z; G@#.B=(z+(2ssize,0)) rotatedaround(z,ang);
+       picture gen; gen=nullpicture;
+       
+       addto gen doublepath z--(z+(.5ssize,0));
+       addto gen doublepath (z+(1.5ssize,0))--(z+(2ssize,0));
+       addto gen doublepath fullcircle scaled ssize shifted (z+(ssize,0));
+       addto gen also thelabel(latex("\textsf{G}") scaled (ssize/6mm) 
+       rotated (-ang), (z+(ssize,0)));
+       
+       draw gen rotatedaround(z,ang) withpen line;
+       
+       putlabel(G@#.D,G@#.B,.5ssize,.5ssize,ang,name,val);
+enddef;
+
+newinternal mid, Fe, auto;
+mid=1; Fe=2; auto=3;
+
+vardef transformer@#(expr z,type,ang)=
+       save trafo;
+       pair tf@#.pi, tf@#.ps, tf@#.si, tf@#.ss, tf@#.m;
+       tf@#.pi=z; tf@#.ps=(z+(0,8coil)) rotatedaround(z,ang);
+       tf@#.si=(z+(2.4coil,0)) rotatedaround(z,ang);
+       tf@#.ss=(z+(2.4coil,8coil)) rotatedaround(z,ang);
+       tf@#.m=(z+(3.4coil,4coil)) rotatedaround(z,ang);
+       
+       picture trafo; trafo=nullpicture;
+       
+       if type=normal:
+       tf@#.pi=z; tf@#.ps=(z+(0,8coil)) rotatedaround(z,ang);
+       tf@#.si=(z+(2.4coil,0)) rotatedaround(z,ang);
+       tf@#.ss=(z+(2.4coil,8coil)) rotatedaround(z,ang);
+               addto trafo doublepath z--(z+(0,coil)){right}..
+               for i=2 upto 6: {left}(z+(0,i*coil)){right}.. endfor
+               {left}(z+(0,7coil))--(z+(0,8coil));
+               addto trafo doublepath (z+(coil,coil))--(z+(coil,7coil));
+               addto trafo doublepath (z+(1.4coil,coil))--(z+(1.4coil,7coil));
+               addto trafo doublepath (z+(2.4coil,0))--(z+(2.4coil,coil)){left}..
+               for i=2 upto 6: {right}(z+(2.4coil,i*coil)){left}.. endfor
+               {right}(z+(2.4coil,7coil))--(z+(2.4coil,8coil));
+       elseif type=mid:
+       tf@#.pi=z; tf@#.ps=(z+(0,8coil)) rotatedaround(z,ang);
+       tf@#.si=(z+(2.4coil,0)) rotatedaround(z,ang);
+       tf@#.ss=(z+(2.4coil,8coil)) rotatedaround(z,ang);
+       tf@#.m=(z+(3.4coil,4coil)) rotatedaround(z,ang);
+               addto trafo doublepath z--(z+(0,coil)){right}..
+               for i=2 upto 6: {left}(z+(0,i*coil)){right}.. endfor
+               {left}(z+(0,7coil))--(z+(0,8coil));
+               addto trafo doublepath (z+(coil,coil))--(z+(coil,7coil));
+               addto trafo doublepath (z+(1.4coil,coil))--(z+(1.4coil,7coil));
+               addto trafo doublepath (z+(2.4coil,0))--(z+(2.4coil,coil)){left}..
+               for i=2 upto 6: {right}(z+(2.4coil,i*coil)){left}.. endfor
+               {right}(z+(2.4coil,7coil))--(z+(2.4coil,8coil));
+               addto trafo doublepath (z+(2.4coil,4coil))--(z+(3.4coil,4coil));
+       elseif type=Fe:
+       tf@#.pi=z rotatedaround(z,ang); tf@#.ps=(z+(0,5.3coil)) rotatedaround(z,ang);
+       tf@#.si=(z+(14coil,0)) rotatedaround(z,ang);
+       tf@#.ss=(z+(14coil,5.228coil)) rotatedaround(z,ang);
+               addto trafo doublepath z+(2coil,-2.5coil)--z+(12coil,-2.5coil)
+               --z+(12coil,7.5coil)--z+(2coil,7.5coil)--cycle;
+               addto trafo doublepath z+(4coil,-.5coil)--z+(10coil,-.5coil)
+               --z+(10coil,5.5coil)--z+(4coil,5.5coil)--cycle;
+               addto trafo doublepath z--z+(2coil,0)--z+(4coil,0.728coil)
+               {right}..{left}z+(4coil,1.3*coil);
+               for i=1 upto 4:
+                       addto trafo doublepath z+(2coil,(i+.5)*coil){left}..
+                       {right}z+(2coil,i*coil)--z+(4coil,(i+0.728)*coil)
+                       {right}..{left}z+(4coil,(i+1.3)*coil);
+               endfor;
+               addto trafo doublepath z+(2coil,5.3coil)--z+(0,5.3coil);
+               for i=0 upto 3:
+                       addto trafo doublepath z+(10coil,i*coil){left}..
+                       {right}z+(10coil,(i+.5)*coil)--z+(12coil,(i+.5+0.728)*coil)
+                       {right}..{left}z+(12coil,(i+.656)*coil);
+               endfor;
+               addto trafo doublepath z+(10coil,4coil){left}..{right}
+               z+(10coil,4.5coil)--z+(12coil,5.228coil)--z+(14coil,5.228coil);
+               addto trafo doublepath z+(12coil,0)--z+(14coil,0);
+       elseif type=auto:
+       tf@#.pi=z rotatedaround(z,ang); tf@#.ps=(z+(0,4coil)) rotatedaround(z,ang);
+       tf@#.si=(z+(4coil,-6coil)) rotatedaround(z,ang);
+       tf@#.ss=(z+(4coil,4coil)) rotatedaround(z,ang);
+               addto trafo doublepath z--z+(2coil,0);
+               addto trafo doublepath z+(2coil,-6coil)--z+(2coil,-5coil){right}..
+               for i=2 upto 10: {left}(z+(2coil,(i-6)*coil)){right}.. endfor
+               {left}(z+(2coil,5coil))--z+(2coil,6coil)--z+(0,6coil);
+               addto trafo doublepath z+(2coil,6coil)--z+(4coil,6coil);
+               addto trafo doublepath z+(2coil,-6coil)--z+(4coil,-6coil);
+       fi;
+       
+       draw trafo rotatedaround(z,ang) withpen line;
+enddef;
+
+//%%<--- Miscellaneous symbols --->%%%
+
+newinternal gndlth, implth, simple, shield;
+gndlth=5mm; implth=7mm; simple=1; shield=2;
+
+vardef ground@#(expr z,type,ang)=
+       save GND;
+       pair gnd@#; % unico pin %
+       gnd@#=z;
+       picture GND; GND=nullpicture;
+       addto GND doublepath z--(z+(0,-.5gndlth)) withpen line;
+       if type=shield:
+               addto GND doublepath (z+(-.5gndlth,-.5gndlth))--(z+(.5gndlth,-.5gndlth)) withpen line;
+               addto GND doublepath (z+(-.35gndlth,-.6gndlth))--(z+(.35gndlth,-.6gndlth)) withpen line;
+               addto GND doublepath (z+(-.2gndlth,-.7gndlth))--(z+(.2gndlth,-.7gndlth)) withpen line;
+       elseif type=simple:
+               addto GND doublepath (z+(-.5gndlth,-.5gndlth))--(z+(.5gndlth,-.5gndlth)) 
+               withpen pencircle scaled 2linewd;
+       fi;
+       draw GND rotatedaround(z,ang);
+enddef;
+
+newinternal junctiondiam;
+junctiondiam=1.25mm;
+
+vardef junction@#(expr z,name)(suffix $)=
+       pair J@#; J@#=z;
+       draw z withpen pencircle scaled junctiondiam;
+       label.$(latex(name),z);
+enddef;
+
+vardef impedance@#(expr z,ang,name,val)=
+       save imp;
+       pair Z@#.l, Z@#.r; % pines %
+       Z@#.l=z;
+       Z@#.r=(z+(1.5implth,0)) rotatedaround(z,ang);
+       picture imp; imp=nullpicture;
+       
+       addto imp doublepath z--(z+(.25implth,0));
+       addto imp doublepath (z+(.25implth,-.18implth))--(z+(.25implth,.18implth))
+       --(z+(1.25implth,.18implth))--(z+(1.25implth,-.18implth))--cycle;
+       addto imp doublepath (z+(1.25implth,0))--(z+(1.5implth,0));
+               
+       draw imp rotatedaround(z,ang) withpen line;
+       
+       putlabel(Z@#.l,Z@#.r,.2implth,.2implth,ang,name,val);
+enddef;
+
+*/
+
+int illuminating = 1;
+
+MultiTerminal lamp(pair beg=(0,0), real dir=0, int type=normal,
+                   Label label="", Label value="", bool draw=true)
+{
+  real r = 0.5*circle_size;
+  MultiTerminal term;
+
+  term = _circle_symbol(beg=beg, dir=dir, label=label, value=value);
+  if (type==normal) {
+    term.pLine.push(-r*dir(45) -- r*dir(45));
+    term.pLine.push(-r*dir(-45) -- r*dir(-45));
+  } else if (type==illuminating) {
+    term.pLine.push((-r,0) -- (-r/2,0));
+    term.pLine.push((r/2,0) -- (r,0));
+    term.pLine.push(scale(r/2)*(E..N..W));
+  }
+  if (draw == true)
+    term.draw();
+  return term;
+}
+
+/*
+
+//%%<--- Mesh current (corriente de malla) --->%%%
+
+newinternal cw, ccw;
+cw=0; ccw=1;
+
+def imesh(expr c,wd,ht,dire,ang,name)=
+       save im,r; picture im; numeric r;
+       ahlength=3platsep; ahangle=20;
+       if ht > wd: r=.2wd elseif ht < wd: r=.2ht fi;
+       im=nullpicture;
+       if dire=cw:
+               addto im doublepath (xpart c - .5wd, ypart c - .5ht)
+               --(xpart c - .5wd, ypart c + .5ht-r){up}
+               ..{right}(xpart c - .5wd + r, ypart c + .5ht)
+               --(xpart c + .5wd - r, ypart c + .5ht){right}
+               ..{down}(xpart c + .5wd,ypart c + .5ht - r)
+               --(xpart c + .5wd,ypart c - .5ht + r){down}
+               ..{left}(xpart c + .5wd - r,ypart c - .5ht)
+               --(xpart c - .25wd, ypart c - .5ht);
+               addto im contour arrowhead (xpart c - .5wd, ypart c - .5ht)
+               --(xpart c - .5wd, ypart c + .5ht-r){up}
+               ..{right}(xpart c - .5wd + r, ypart c + .5ht)
+               --(xpart c + .5wd - r, ypart c + .5ht){right}
+               ..{down}(xpart c + .5wd,ypart c + .5ht - r)
+               --(xpart c + .5wd,ypart c - .5ht + r){down}
+               ..{left}(xpart c + .5wd - r,ypart c - .5ht)
+               --(xpart c - .25wd, ypart c - .5ht);
+       elseif dire=ccw:
+               addto im doublepath (xpart c + .5wd, ypart c - .5ht)
+               --(xpart c + .5wd, ypart c + .5ht-r){up}
+               ..{left}(xpart c + .5wd - r, ypart c + .5ht)
+               --(xpart c - .5wd + r, ypart c + .5ht){left}
+               ..{down}(xpart c - .5wd,ypart c + .5ht - r)
+               --(xpart c - .5wd,ypart c - .5ht + r){down}
+               ..{right}(xpart c - .5wd + r,ypart c - .5ht)
+               --(xpart c + .25wd, ypart c - .5ht);
+               addto im contour arrowhead (xpart c + .5wd, ypart c - .5ht)
+               --(xpart c + .5wd, ypart c + .5ht-r){up}
+               ..{left}(xpart c + .5wd - r, ypart c + .5ht)
+               --(xpart c - .5wd + r, ypart c + .5ht){left}
+               ..{down}(xpart c + .5wd,ypart c + .5ht - r)
+               --(xpart c - .5wd,ypart c - .5ht + r){down}
+               ..{right}(xpart c - .5wd + r,ypart c - .5ht)
+               --(xpart c + .25wd, ypart c - .5ht);
+       fi;
+       
+       if labeling=rotatelabel:
+               addto im also thelabel(latex("$" & name & "$"),c);
+       elseif labeling=norotatelabel:
+               addto im also thelabel(latex("$" & name & "$") rotatedaround(c,-ang),c);
+       fi;
+       
+       draw im rotatedaround (c,ang) withpen line;
+enddef;
+
+//%%<--- Reostatos --->%%%
+
+newinternal rheolth, Rrheo, Lrheo; 
+rheolth=2mm; Rrheo=1; Lrheo=2;
+
+vardef rheostat@#(expr z,type,ang)=
+       save reo; picture reo; reo=nullpicture;
+       pair rh@#.i, rh@#.s, rh@#.r;
+       rh@#.i=z; rh@#.s=(z+(0,6rheolth)) rotatedaround(z,ang);
+       rh@#.r=(z+(3rheolth,6rheolth)) rotatedaround(z,ang);
+       
+       ahangle=20; ahlength=rheolth;
+
+       if type=Lrheo:
+               addto reo doublepath (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
+               --(z+(4rheolth,-.7rheolth));
+               addto reo contour arrowhead (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
+               --(z+(4rheolth,-.9rheolth));
+       
+               addto reo doublepath z--(z+(rheolth,0)){down}.. for i=2 upto 4:
+               {up}(z+(i*rheolth,0)){down}.. endfor {up}(z+(5rheolth,0))--(z+(6rheolth,0));
+       
+               reo=reo rotatedaround(z,90);
+       elseif type=Rrheo:
+               addto reo doublepath (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
+               --(z+(4rheolth,-.7rheolth));
+               addto reo contour arrowhead (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
+               --(z+(4rheolth,-.9rheolth));
+       
+               addto reo doublepath z--(z+(1.5rheolth,0))--(z+(1.75rheolth,.75rheolth))--
+               for i=.5 step .5 until 2.5:     (z+((1.75+i)*rheolth,((-1)**(2i))*.75rheolth))--
+               endfor (z+(4.5rheolth,0))--(z+(6rheolth,0)) withpen line;
+       
+               reo=reo rotatedaround(z,90);
+       fi;
+       draw reo rotatedaround(z,ang) withpen line;
+enddef;
+
+*/
+
+// Loop symbols for Kirchhoff's rules.
+
+void kirchhoff_loop(picture pic=currentpicture, pair points[],
+                    pen outline=kirchhoff_pen, real aspace=-1) {
+  // draw kirchhoff loop underneath currentpicture
+  picture newpic;
+  int i;
+  guide g;
+  pair a = points[0] - points[points.length-1];  // arrow distance
+  if (aspace < 0)
+    aspace = 3*linewidth(outline);  // one dot diameter
+  real alength = max(0.5*length(a), length(a) - aspace - linewidth(outline)/2);
+  a = alength*unit(a);
+  pair astop = points[points.length-1] + a;
+  dot(newpic, points[0], scale(3)*outline);
+  for (int i=0; i < points.length; ++i)
+    g = g--points[i];
+  g = g -- astop;
+  draw(newpic, g, outline, Arrow(size=3*linewidth(outline)));
+  add(pic, newpic, above=false);
+}