1 /* Useful functions for drawing circuit diagrams.
4 * Copyright (C) 2003 GS Bustamante Argañaraz
5 * 2008-2011 W. Trevor King <wking@drexel.edu>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * Based on MetaPost's MakeCirc by Gustavo Sebastian Bustamante Argañaraz.
23 * http://www.ctan.org/tex-archive/help/Catalogue/entries/makecirc.html
26 // Command definitions for easier labeling
28 texpreamble("\def\ohm{\ensuremath{\,\Omega}}");
29 texpreamble("\def\kohm{\,k\ensuremath{\Omega}}");
30 texpreamble("\def\modarg#1#2{\setbox0=\hbox{$\mkern-1mu/#2^\circ$}\dp0=.21ex $#1\underline{\box0}$}");
33 int norotatelabel = 1;
34 int labeling = rotatelabel;
36 // Macros for the pens, I define them as such so when they expand,
37 // look for the last value assigned to linewd and use it
38 // (thanks to JLD). The linewd value assigns it as newinternal to
39 // be able to change it «from out».
43 pen line = linewidth(linewd);
44 pen misc = linewidth(0.8*linewd);
45 pen kirchhoff_pen = linewidth(10*linewd)+gray(0.7);
47 // Arrowhead definitions
49 real ahlength = 4bp; // Arrowhead length
50 real ahangle = 30; // Arrowhead angle
52 path miscahead (path p)
54 real t = reltime(p, 1.0);
57 path a = shift(A)*((0,0)--(scale(ahlength)*rotate(15)*u));
58 path b = shift(A)*((0,0)--(scale(ahlength)*rotate(-15)*u));
59 return (a & reverse(a) & b & reverse(b))--cycle;
62 path fullhead (path p, real length=ahlength, real angle=ahangle)
64 real t = reltime(p, 1.0);
67 path a = shift(A)*((0,0)--(scale(length)*rotate(angle/2)*u));
68 path b = shift(A)*((0,0)--(scale(length)*rotate(-angle/2)*u));
69 return (A -- a -- reverse(b) --cycle);
72 path bjtahead (path p)
74 pair A = point(p,reltime(p,0.7));
75 pair u = -dir(p,reltime(p,0.5));
76 path a = shift(A)*((0,0)--(scale(ahlength)*rotate(20)*u));
77 path b = shift(A)*((0,0)--(scale(ahlength)*rotate(-20)*u));
78 return (a & reverse(a) & b & reverse(b))--cycle;
81 path txtahead (path p)
83 pair A = point(p,reltime(p,1.0));
84 pair B = point(p,reltime(p,0.97));
85 pair u = dirtime(p,reltime(p,1.0));
86 return A{-u}..(A - scale(7)*rotate(15)*u)--B
87 --(A - scale(7)*rotate(-15)*u)..A{u}--cycle;
90 // function to wire the symbols together
92 int nsq=0, udsq=2, rlsq=3;
94 void wire(pair pin_beg, pair pin_end, int type=nsq, real dist=0)
98 draw(pin_beg--pin_end, line);
99 } else if (type==udsq) {
100 draw(pin_beg--(pin_beg.x,pin_end.y)--pin_end, line);
101 } else if (type==rlsq) {
102 draw(pin_beg--(pin_end.x,pin_beg.y)--pin_end, line);
104 write("Error, unrecognized wire type ",type);
108 draw(pin_beg--(pin_beg+(0,dist))--(pin_end.x,pin_beg.y + dist)
110 } else if (type==rlsq) {
111 draw(pin_beg--(pin_beg+(dist,0))--(pin_beg.x + dist,pin_end.y)
114 write("Error, unrecognized wire type ",type);
119 // Macro to center text among two pins
121 bool witharrow=false, noarrow=true;
123 void ctext(pair pin_beg, pair pin_end, string txt, bool type)
128 } else if (type==witharrow) {
129 draw(ctxt, pin_beg--pin_end);
130 draw(ctxt, txtahead(pin_beg--pin_end));
131 draw(ctxt, txtahead(reverse(pin_beg--pin_end)));
133 write("Error, unrecognized ctext type ",type);
135 label(ctxt, txt, 0.5(pin_beg+pin_end));
136 add(currentpicture, ctxt);
139 // Definition of lbsep (label separation), distance among symbol and label.
144 // ----- Here the symbols begin --------
156 path pLine[]; // cyclic paths are filled in
159 void operator init(pair beg, real len, real ang, real lchar, real lcharv, string name, string val, path pLine[]={}, path pMisc[]={}) {
161 this.end = beg+rotate(ang)*(len,0);
162 this.mid = (this.beg + this.end)/2;
164 this.ang = ang % 360;
166 this.lcharv = lcharv;
173 void putlabel(picture pic=currentpicture) {
175 pair pName, pVal; // point
176 real rName, rVal; // rotated by
178 if (labeling==rotatelabel) {
179 pName = (lchar+lbsep)*dir (90+ang);
180 pVal = (lcharv+lbsep)*dir (270+ang);
183 if (ang <= 90 || ang > 270) {
186 } else if (ang > 90 && ang <= 270) {
190 } else if (labeling==norotatelabel) {
194 pName = (lchar+.25lbsep)*dir (90+ang);
195 pVal = (lcharv+.25lbsep)*dir (270+ang);
198 } else if (ang < 90) {
199 pName = (lchar)*dir (90+ang);
200 pVal = (lcharv)*dir (270+ang);
203 } else if (ang == 90) {
204 pName = (lchar+.25lbsep)*dir (90+ang);
205 pVal = (lcharv+.25lbsep)*dir (270+ang);
208 } else if (90 < ang && ang < 180) {
209 pName = (lchar)*dir (90+ang);
210 pVal = (lcharv)*dir (270+ang);
213 } else if (ang == 180) {
214 pName = (lchar+.25lbsep)*dir (90+ang);
215 pVal = (lcharv+.25lbsep)*dir (270+ang);
218 } else if (ang > 180 && ang < 270) {
219 pName = (lchar)*dir (90+ang);
220 pVal = (lcharv)*dir (270+ang);
223 } else if (ang == 270) {
224 pName = (lchar+.25lbsep)*dir (90+ang);
225 pVal = (lcharv+.25lbsep)*dir (270+ang);
228 } else if (270 < ang && ang < 360) {
229 pName = (lchar)*dir (90+ang);
230 pVal = (lcharv)*dir (270+ang);
235 Label lName = rotate(rName)*Label(name);
236 label(picL, lName, pName, aName);
237 Label lVal = rotate(rVal)*Label(val);
238 label(picL, lVal, pVal, aVal);
239 add(pic, picL, (end-beg)/2);
242 /* Shift position by a */
249 /* Rather than placing the element with a point and direction (beg,
250 * ang), center an element between the pairs a and b. The optional
251 * offset shifts the element in the direction rotated(90)*(b-a)
252 * (i.e. up for offset > 0 if b is directly right of a).
254 void centerto(pair a, pair b, real offset=0) {
255 this.ang = degrees(b-a);
257 - unit(b-a)*this.len/2 + offset*dir(this.ang+90);
258 this.end = this.beg+rotate(ang)*(this.len,0);
259 this.mid = (this.beg + this.end)/2;
262 void draw(picture pic=currentpicture) {
264 for (int i=0; i< pLine.length; i+=1) {
265 draw(picT, rotate(ang)*pLine[i], line);
266 if (cyclic(pLine[i]))
267 fill(picT, rotate(ang)*pLine[i], line);
269 for (int i=0; i< pMisc.length; i+=1) {
270 draw(picT, rotate(ang)*pMisc[i], misc);
271 if (cyclic(pMisc[i]))
272 fill(picT, rotate(ang)*pMisc[i], misc);
279 void centerto(TwoTerminal reference, TwoTerminal target, real offset=0,
282 if (reverse == false)
283 target.centerto(reference.beg, reference.end, offset);
285 target.centerto(reference.end, reference.beg, offset);
288 // --- Resistor (Resistencia) ---
291 int normal=0, variable=2;
293 TwoTerminal resistor(pair beg=(0,0), real ang=0, int type=normal,
294 string name="", string val="", bool draw=true)
296 path pLine, pMisc[]={};
299 pLine = (0,0)--(2rstlth,0)--(2.25rstlth,.75rstlth);
300 for (real i=.5; i<=2.5; i+=0.5)
301 pLine = pLine--((2.25+i)*rstlth,((-1)**(2i))*.75rstlth);
302 pLine = pLine -- (5rstlth,0)--(7rstlth,0);
305 } else if (type==variable) {
307 pMisc.push((2rstlth,-rstlth)--(5.5rstlth,rstlth));
308 pMisc.push(miscahead((2rstlth,-rstlth)--(5.5rstlth,rstlth)));
310 write("Error, unrecognized resistor type ",type);
312 term = TwoTerminal(beg, 7rstlth, ang, .8rstlth, .8rstlth, name, val, pLine, pMisc);
318 // --- Inductor (bobina) ---
323 TwoTerminal inductor(pair beg=(0,0), real ang=0, int type=Up, string name="",
324 string val="", bool draw=true)
330 pLine = (0,0)--(coil,0);
331 for (int i=2; i<=4; i+=1)
332 pLine = pLine{N}..{S}(i*coil,0);
333 pLine = pLine{N}..{S}(5coil,0)--(6coil,0);
334 } else if (type==Down) {
335 pLine = (0,0)--(coil,0);
336 for (int i=2; i<=4; i+=1)
337 pLine = pLine{S}..{N}(i*coil,0);
338 pLine = pLine{S}..{N}(5coil,0)--(6coil,0);
339 // the original makecirc changed labelangle to ang-180
341 write("Error, unrecognized inductor type ",type);
343 term = TwoTerminal(beg, 6coil, ang, coil, coil, name, val, pLine);
344 // the original makecirc used .5coil for lcharv
350 // --- Capacitor (condensador) ---
353 int normal=0, electrolytic=1, variable=2, variant=3;
355 TwoTerminal capacitor(pair beg=(0,0), real ang=0, int type=normal,
356 string name="", string val="", bool draw=true)
358 path pLine[]={}, pMisc[]={};
361 pLine.push((0,0)--(3platsep,0));
362 pLine.push((4platsep,0)--(7platsep,0));
365 pLine.push((3platsep,-2.5platsep)--(3platsep,2.5platsep));
366 pLine.push((4platsep,-2.5platsep)--(4platsep,2.5platsep));
367 } else if (type==electrolytic) {
368 pLine.push((3platsep,-1.8platsep)--(3platsep,1.8platsep));
369 pLine.push((2platsep,-2.5platsep)--(4platsep,-2.5platsep)
370 --(4platsep,+2.5platsep)--(2platsep,2.5platsep));
371 } else if (type==variable) {
372 pLine.push((3platsep,-2.5platsep)--(3platsep,2.5platsep));
373 pLine.push((4platsep,-2.5platsep)--(4platsep,2.5platsep));
374 pMisc.push((platsep,-2.5platsep)--(6platsep,2.5platsep));
376 pMisc.push(miscahead((platsep,-2.5platsep)--(6platsep,2.5platsep)));
377 } else if (type==variant) {
378 pLine.push((3platsep,-2.5platsep)--(3platsep,2.5platsep));
379 pLine.push((4.5platsep,-2.5platsep)..(4platsep,0)..(4.5platsep,2.5platsep));
381 write("Error, unrecognized capacitor type ",type);
383 term = TwoTerminal(beg, 7platsep, ang, 2.5platsep, 2.5platsep, name, val, pLine, pMisc);
389 // --- Diode (diodo) ---
393 // I droped the pin parameters, since other device (e.g. electrolytic
394 // capacitors) are also polarized. The positioning method centerto(),
395 // provides enough flexibility.
397 TwoTerminal diode(pair beg=(0,0), real ang=0, int type=normal, string name="",
398 string val="", bool draw=true)
400 path pLine[]={}, pMisc[]={};
404 pLine.push((0,0)--(diodeht,0)--(diodeht,.5diodeht)--(2diodeht,0)--(diodeht,-.5diodeht)--(diodeht,0));
405 pLine.push((2diodeht,0)--(3diodeht,0));
406 lchar = 0.6diodeht; lcharv = 0.6diodeht;
409 pLine.push((2diodeht,-.5diodeht)--(2diodeht,.5diodeht));
410 } else if (type==zener) {
411 pLine.push((2.5diodeht,-.5diodeht)--(2diodeht,-.5diodeht)--(2diodeht,.5diodeht)--(1.5diodeht,.5diodeht));
412 } else if (type==LED) {
413 path a = (diodeht,.5diodeht)--(2diodeht,0);
414 pair u = unit((.5,1)); // perpendicular to a
415 path b = (0,0)--diodeht*u;
416 pLine.push((2diodeht,-.5diodeht)--(2diodeht,.5diodeht));
418 pMisc.push(shift(point(a,reltime(a,0.25))+point(b,0.33))*((0,0)--diodeht*u));
419 pMisc.push(shift(point(a,reltime(a,0.60))+point(b,0.33))*((0,0)--diodeht*u));
420 pMisc.push(fullhead(pMisc[0], 0.4diodeht, 30));
421 pMisc.push(fullhead(pMisc[1], 0.4diodeht, 30));
423 write("Error, unrecognized capacitor type ",type);
425 term = TwoTerminal(beg, 3diodeht, ang, lchar, lcharv, name, val,pLine,pMisc);
431 //--- Battery (bater'ia) ---
435 TwoTerminal battery(pair beg=(0,0), real ang=0, string name="", string val="",
438 path pLine[]={}, pMisc[]={};
442 pLine.push((0,0)--(0.4bsize,0));
443 pLine.push((1.4bsize,0)--(1.8bsize,0));
445 for (int i=0; i<3; i+=1) {
446 pLine.push(((0.4+0.4i)*bsize, -0.2bsize)--((0.4+0.4i)*bsize, 0.2bsize));
447 pLine.push(((0.6+0.4i)*bsize, -0.6bsize)--((0.6+0.4i)*bsize, 0.6bsize));
449 lchar = 0.6bsize; lcharv = 0.6bsize;
451 term = TwoTerminal(beg, 1.8bsize, ang, lchar, lcharv, name, val,pLine,pMisc);
457 //--- Switches (Llaves) ---
460 real ssep=3mm, swt=1.2ssep; // TODO remove swt?
462 /* `switch' is a Asymptote keyword (or it should be), so append SPST
463 * for Single Pole Single Throw.
465 TwoTerminal switchSPST(pair beg=(0,0), real ang=0, int type=NO, string name="",
466 string val="", bool draw=true)
468 path pLine[]={}, pMisc[]={};
472 pLine.push((0,0)--(0.7ssep,0));
473 pLine.push((1.7ssep,ssep/3)--(1.7ssep,0)--(2.4ssep,0));
474 lchar = 0.6ssep; lcharv = 0.6ssep;
477 pLine.push((0.7ssep,0)--(1.8ssep,0.7ssep));
478 } else if (type==NC) {
479 pLine.push((0.7ssep,0)--(2ssep,ssep/3));
481 write("Error, unrecognized switchSPST type ",type);
483 term = TwoTerminal(beg, 2.4ssep, ang, lchar, lcharv, name, val, pLine,pMisc);
489 //--- Current (Corriente) ---
493 // adjusted from makecirc original to center arrowhead under text
494 TwoTerminal current(pair beg=(0,0), real ang=0, string name="", string val="",
497 path pLine[]={}, pMisc[]={};
500 lchar = 0.4isize; lcharv = 0.4isize;
501 pLine.push((0,0)--(1.5isize,0));
502 pLine.push((1.5isize,0)--(2isize,0));
503 pMisc.push(fullhead(pLine[0], isize, 45));
504 term = TwoTerminal(beg, 2isize, ang, lchar, lcharv, name, val, pLine, pMisc);
510 //--- Circle-based symbols (for internal use) --
512 real circle_size=6mm;
514 TwoTerminal _two_terminal_circle(pair beg=(0,0), real ang=0, string name="",
517 path pLine[]={}, pMisc[]={};
518 real len, lchar, lcharv, r = circle_size/2;
524 c = (circle_size, 0);
525 pLine.push((0,0)--(r,0));
526 pLine.push(shift(c)*scale(r)*(E..N..W..S..E));
527 pLine.push((3r,0)--(4r,0));
528 term = TwoTerminal(beg, len, ang, lchar, lcharv, name, val, pLine, pMisc);
532 //--- Sources (fuentes de alimentaci'on) ---
534 int AC=0,DC=1,I=2,V=3;
536 TwoTerminal source(pair beg=(0,0), real ang=0, int type=AC, string name="",
537 string val="", bool draw=true)
541 if (type == AC || type == I || type == V) {
542 real s = circle_size;
543 term = _two_terminal_circle(beg=beg, ang=ang, name=name, val=val);
545 term.pLine.push((2s/3,0){NE}..{E}((1/3+.5)*s,.2s)..{SE}(s,0)..{E}((2/3+.5)*s,-.2s)..{NE}(4s/3,0));
546 } else if (type == I) {
547 term.pLine.push((2s/3,0)--(4s/3,0));
548 term.pLine.push(fullhead(term.pLine[3], 4s/15, 30));
549 } else if (type == V) {
550 term.pLine.push((1.05s,0)--(1.45s,0));
551 term.pLine.push((1.25s,-.2s)--(1.25s,.2s));
552 term.pLine.push((.95s,0)--(.55s,0));
554 } else if (type == DC) {
556 real len, lchar, lcharv;
558 lchar = 0.6len; lcharv = .6len;
559 pLine.push((0,0)--(0.4len,0));
560 pLine.push((.6len,0)--(len,0));
561 pLine.push((.4len,-.2len)--(.4len,.2len));
562 pLine.push((.6len,-.6len)--(.6len,.6len));
563 term = TwoTerminal(beg, len, ang, lchar, lcharv, name, val, pLine);
572 //%%<--- Transistor --->%%%
573 newinternal npn, pnp, cnpn, cpnp, bjtlth;
574 npn=1; pnp=-1; cnpn=0; cpnp=2; bjtlth=7mm;
576 vardef transistor@#(expr z,type,ang)=
578 pair T@#.B,T@#.E,T@#.C; % pines: Base, Emisor, Colector %
580 T@#.E=(z+(bjtlth,-.75bjtlth)) rotatedaround(z,ang);
581 T@#.C=(z+(bjtlth,.75bjtlth)) rotatedaround(z,ang);
585 addto BJT doublepath z--(z+(.5bjtlth,0)) withpen line;
586 addto BJT doublepath (z+(.5bjtlth,-.5bjtlth))--(z+(.5bjtlth,.5bjtlth)) withpen line;
587 addto BJT doublepath (z+(.5bjtlth,.2bjtlth))--(z+(bjtlth,.5bjtlth))
588 --(z+(bjtlth,.75bjtlth)) withpen line;
591 addto BJT doublepath (z+(.5bjtlth,-.2bjtlth))--(z+(bjtlth,-.5bjtlth))
592 --(z+(bjtlth,-.75bjtlth)) withpen line;
593 addto BJT contour bjtahead (z+(.5bjtlth,-.2bjtlth))
594 --(z+(bjtlth,-.5bjtlth)) withpen line;
596 addto BJT doublepath (z+(.5bjtlth,-.2bjtlth))--(z+(bjtlth,-.5bjtlth))
597 --(z+(bjtlth,-.75bjtlth)) withpen line;
598 addto BJT contour bjtahead (z+(.5bjtlth,-.2bjtlth))
599 --(z+(bjtlth,-.5bjtlth)) withpen line;
600 addto BJT doublepath fullcircle scaled 1.3bjtlth shifted (z+(.65bjtlth,0))
603 addto BJT doublepath (z+(bjtlth,-.75bjtlth))--(z+(bjtlth,-.5bjtlth))
604 --(z+(.5bjtlth,-.2bjtlth)) withpen line;
605 addto BJT contour bjtahead (z+(bjtlth,-.5bjtlth))
606 --(z+(.5bjtlth,-.2bjtlth)) withpen line;
608 addto BJT doublepath (z+(bjtlth,-.75bjtlth))--(z+(bjtlth,-.5bjtlth))
609 --(z+(.5bjtlth,-.2bjtlth)) withpen line;
610 addto BJT contour bjtahead (z+(bjtlth,-.5bjtlth))
611 --(z+(.5bjtlth,-.2bjtlth)) withpen line;
612 addto BJT doublepath fullcircle scaled 1.3bjtlth shifted (z+(.65bjtlth,0)) withpen line;
615 draw BJT rotatedaround(z,ang);
618 //%%<--- Measurement instruments (Intrumentos de medicion)--->%%%
619 newinternal volt, ampere, watt;
620 volt=0; ampere=1; watt=2;
622 vardef meains@#(expr z,type,ang,name)=
624 pair mi@#.l, mi@#.r, mi@#.p; % pines %
625 mi@#.l=z; mi@#.r=(z+(2ssize,0)) rotatedaround(z,ang);
627 picture meter; meter=nullpicture;
628 addto meter doublepath z--(z+(.5ssize,0));
629 addto meter doublepath (z+(1.5ssize,0))--(z+(2ssize,0));
630 if (type=volt) || (type=ampere):
631 addto meter doublepath fullcircle scaled ssize shifted (z+(ssize,0));
633 addto meter also thelabel(latex("\textsf{V}") scaled (ssize/6mm)
634 rotated (-ang), (z+(ssize,0)));
636 addto meter also thelabel(latex("\textsf{A}") scaled (ssize/6mm)
637 rotated (-ang), (z+(ssize,0)));
640 mi@#.p=(z+(ssize,-ssize)) rotatedaround(z,ang);
641 addto meter doublepath (z+(.5ssize,-.5ssize))--(z+(.5ssize,.5ssize))
642 --(z+(1.5ssize,.5ssize))--(z+(1.5ssize,-.5ssize))--cycle;
643 addto meter doublepath (z+(ssize,-.5ssize))--(z+(ssize,-ssize));
644 addto meter also thelabel(latex("\textsf{W}") scaled (ssize/6mm)
645 rotated (-ang), (z+(ssize,0)));
648 draw meter rotatedaround(z,ang) withpen line;
650 if labeling=rotatelabel:
651 if ((ang > (-90)) && (ang <= 90)) || ((ang > 270) && (ang <= 450)):
652 label(latex(name) rotatedaround (.5[mi@#.l,mi@#.r],ang),
653 (.5ssize+lbsep)*dir (90+ang) shifted .5[mi@#.l,mi@#.r]);
654 elseif ((ang > 90) && (ang <= 270)) || ((ang > (-270)) && (ang <= (-90))):
655 label(latex(name) rotatedaround (.5[mi@#.l,mi@#.r],180+ang),
656 (.5ssize+lbsep)*dir (90+ang) shifted .5[mi@#.l,mi@#.r]);
658 elseif labeling=norotatelabel:
660 label.top(latex(name), (.5ssize+.25lbsep)*dir (90+ang)
661 shifted .5[mi@#.l,mi@#.r]);
662 elseif (ang > 0) && (ang < 90):
663 label.ulft(latex(name), (.5ssize)*dir (90+ang)
664 shifted .5[mi@#.l,mi@#.r]);
666 label.lft(latex(name),(.5ssize+.25lbsep)*dir (90+ang)
667 shifted .5[mi@#.l,mi@#.r]);
668 elseif (90 < ang) && (ang < 180):
669 label.llft(latex(name),(.5ssize)*dir (90+ang)
670 shifted .5[mi@#.l,mi@#.r]);
671 elseif (ang = 180) || (ang = (-180)):
672 label.bot(latex(name), (.5ssize+.25lbsep)*dir (90+ang)
673 shifted .5[mi@#.l,mi@#.r]);
674 elseif ((ang > 180) && (ang < 270)) || ((ang > (-180)) && (ang < (-90))):
675 label.lrt(latex(name),(.5ssize)*dir (90+ang)
676 shifted .5[mi@#.l,mi@#.r]);
677 elseif (ang = 270) || (ang = (-90)):
678 label.rt(latex(name), (.5ssize+.25lbsep)*dir (90+ang)
679 shifted .5[mi@#.l,mi@#.r]);
680 elseif ((270 < ang) && (ang < 360)) || ((ang < 0) && (ang > (-90))):
681 label.urt(latex(name),(.5ssize)*dir (90+ang)
682 shifted .5[mi@#.l,mi@#.r]);
687 // --- Electrical machines (maquinas electricas) ---
689 TwoTerminal motor(pair beg, real ang, string name, string val)
695 pLine = (0,0)--(coil,0);
696 for (int i=2; i<=4; i+=1)
697 pLine = pLine{N}..{S}(i*coil,0);
698 pLine = pLine{N}..{S}(5coil,0)--(6coil,0);
699 } else if (type==Down) {
700 pLine = (0,0)--(coil,0);
701 for (int i=2; i<=4; i+=1)
702 pLine = pLine{S}..{N}(i*coil,0);
703 pLine = pLine{S}..{N}(5coil,0)--(6coil,0);
704 // original makecirc changed labelangle to ang-180
706 term = TwoTerminal(beg, 6coil, ang, coil, coil, name, val, pLine);
707 // original makecirc used .5coil for lcharv
711 M@#.D=z; M@#.B=(z+(2ssize,0)) rotatedaround(z,ang);
712 picture mot; mot=nullpicture;
714 addto mot doublepath z--(z+(.4ssize,0));
715 addto mot doublepath (z+(1.6ssize,0))--(z+(2ssize,0));
716 addto mot doublepath fullcircle scaled ssize shifted (z+(ssize,0));
717 addto mot also thelabel(latex("\textsf{M}") scaled (ssize/6mm)
718 rotated (-ang), (z+(ssize,0)));
720 path p,q,r,s,ca,cb,c,hc;
721 p=(z+(.6ssize,.075ssize))--(z+(.4ssize,.075ssize));
722 q=(z+(.4ssize,.075ssize))--(z+(.4ssize,-.075ssize));
723 ca=(z+(.4ssize,-.075ssize))--(z+(.6ssize,-.075ssize));
726 r=(z+(1.4ssize,.075ssize))--(z+(1.6ssize,.075ssize));
727 s=(z+(1.6ssize,.075ssize))--(z+(1.6ssize,-.075ssize));
728 cb=(z+(1.6ssize,-.075ssize))--(z+(1.4ssize,-.075ssize));
730 c=fullcircle scaled ssize shifted (z+(ssize,0));
731 hc=halfcircle scaled ssize rotated 270 shifted (z+(ssize,0));
733 addto mot contour buildcycle(p,q,ca,c);
734 addto mot doublepath buildcycle(p,q,ca,c);
736 addto mot contour buildcycle(cb,s,r,hc);
737 addto mot doublepath buildcycle(cb,s,r,hc);
739 draw mot rotatedaround(z,ang) withpen line;
741 putlabel(M@#.D,M@#.B,.5ssize,.5ssize,ang,name,val);
744 vardef generator@#(expr z,ang,name,val)=
746 pair G@#.D, G@#.B; % pines %
747 G@#.D=z; G@#.B=(z+(2ssize,0)) rotatedaround(z,ang);
748 picture gen; gen=nullpicture;
750 addto gen doublepath z--(z+(.5ssize,0));
751 addto gen doublepath (z+(1.5ssize,0))--(z+(2ssize,0));
752 addto gen doublepath fullcircle scaled ssize shifted (z+(ssize,0));
753 addto gen also thelabel(latex("\textsf{G}") scaled (ssize/6mm)
754 rotated (-ang), (z+(ssize,0)));
756 draw gen rotatedaround(z,ang) withpen line;
758 putlabel(G@#.D,G@#.B,.5ssize,.5ssize,ang,name,val);
761 newinternal mid, Fe, auto;
764 vardef transformer@#(expr z,type,ang)=
766 pair tf@#.pi, tf@#.ps, tf@#.si, tf@#.ss, tf@#.m;
767 tf@#.pi=z; tf@#.ps=(z+(0,8coil)) rotatedaround(z,ang);
768 tf@#.si=(z+(2.4coil,0)) rotatedaround(z,ang);
769 tf@#.ss=(z+(2.4coil,8coil)) rotatedaround(z,ang);
770 tf@#.m=(z+(3.4coil,4coil)) rotatedaround(z,ang);
772 picture trafo; trafo=nullpicture;
775 tf@#.pi=z; tf@#.ps=(z+(0,8coil)) rotatedaround(z,ang);
776 tf@#.si=(z+(2.4coil,0)) rotatedaround(z,ang);
777 tf@#.ss=(z+(2.4coil,8coil)) rotatedaround(z,ang);
778 addto trafo doublepath z--(z+(0,coil)){right}..
779 for i=2 upto 6: {left}(z+(0,i*coil)){right}.. endfor
780 {left}(z+(0,7coil))--(z+(0,8coil));
781 addto trafo doublepath (z+(coil,coil))--(z+(coil,7coil));
782 addto trafo doublepath (z+(1.4coil,coil))--(z+(1.4coil,7coil));
783 addto trafo doublepath (z+(2.4coil,0))--(z+(2.4coil,coil)){left}..
784 for i=2 upto 6: {right}(z+(2.4coil,i*coil)){left}.. endfor
785 {right}(z+(2.4coil,7coil))--(z+(2.4coil,8coil));
787 tf@#.pi=z; tf@#.ps=(z+(0,8coil)) rotatedaround(z,ang);
788 tf@#.si=(z+(2.4coil,0)) rotatedaround(z,ang);
789 tf@#.ss=(z+(2.4coil,8coil)) rotatedaround(z,ang);
790 tf@#.m=(z+(3.4coil,4coil)) rotatedaround(z,ang);
791 addto trafo doublepath z--(z+(0,coil)){right}..
792 for i=2 upto 6: {left}(z+(0,i*coil)){right}.. endfor
793 {left}(z+(0,7coil))--(z+(0,8coil));
794 addto trafo doublepath (z+(coil,coil))--(z+(coil,7coil));
795 addto trafo doublepath (z+(1.4coil,coil))--(z+(1.4coil,7coil));
796 addto trafo doublepath (z+(2.4coil,0))--(z+(2.4coil,coil)){left}..
797 for i=2 upto 6: {right}(z+(2.4coil,i*coil)){left}.. endfor
798 {right}(z+(2.4coil,7coil))--(z+(2.4coil,8coil));
799 addto trafo doublepath (z+(2.4coil,4coil))--(z+(3.4coil,4coil));
801 tf@#.pi=z rotatedaround(z,ang); tf@#.ps=(z+(0,5.3coil)) rotatedaround(z,ang);
802 tf@#.si=(z+(14coil,0)) rotatedaround(z,ang);
803 tf@#.ss=(z+(14coil,5.228coil)) rotatedaround(z,ang);
804 addto trafo doublepath z+(2coil,-2.5coil)--z+(12coil,-2.5coil)
805 --z+(12coil,7.5coil)--z+(2coil,7.5coil)--cycle;
806 addto trafo doublepath z+(4coil,-.5coil)--z+(10coil,-.5coil)
807 --z+(10coil,5.5coil)--z+(4coil,5.5coil)--cycle;
808 addto trafo doublepath z--z+(2coil,0)--z+(4coil,0.728coil)
809 {right}..{left}z+(4coil,1.3*coil);
811 addto trafo doublepath z+(2coil,(i+.5)*coil){left}..
812 {right}z+(2coil,i*coil)--z+(4coil,(i+0.728)*coil)
813 {right}..{left}z+(4coil,(i+1.3)*coil);
815 addto trafo doublepath z+(2coil,5.3coil)--z+(0,5.3coil);
817 addto trafo doublepath z+(10coil,i*coil){left}..
818 {right}z+(10coil,(i+.5)*coil)--z+(12coil,(i+.5+0.728)*coil)
819 {right}..{left}z+(12coil,(i+.656)*coil);
821 addto trafo doublepath z+(10coil,4coil){left}..{right}
822 z+(10coil,4.5coil)--z+(12coil,5.228coil)--z+(14coil,5.228coil);
823 addto trafo doublepath z+(12coil,0)--z+(14coil,0);
825 tf@#.pi=z rotatedaround(z,ang); tf@#.ps=(z+(0,4coil)) rotatedaround(z,ang);
826 tf@#.si=(z+(4coil,-6coil)) rotatedaround(z,ang);
827 tf@#.ss=(z+(4coil,4coil)) rotatedaround(z,ang);
828 addto trafo doublepath z--z+(2coil,0);
829 addto trafo doublepath z+(2coil,-6coil)--z+(2coil,-5coil){right}..
830 for i=2 upto 10: {left}(z+(2coil,(i-6)*coil)){right}.. endfor
831 {left}(z+(2coil,5coil))--z+(2coil,6coil)--z+(0,6coil);
832 addto trafo doublepath z+(2coil,6coil)--z+(4coil,6coil);
833 addto trafo doublepath z+(2coil,-6coil)--z+(4coil,-6coil);
836 draw trafo rotatedaround(z,ang) withpen line;
839 //%%<--- Miscellaneous symbols --->%%%
841 newinternal gndlth, implth, simple, shield;
842 gndlth=5mm; implth=7mm; simple=1; shield=2;
844 vardef ground@#(expr z,type,ang)=
846 pair gnd@#; % unico pin %
848 picture GND; GND=nullpicture;
849 addto GND doublepath z--(z+(0,-.5gndlth)) withpen line;
851 addto GND doublepath (z+(-.5gndlth,-.5gndlth))--(z+(.5gndlth,-.5gndlth)) withpen line;
852 addto GND doublepath (z+(-.35gndlth,-.6gndlth))--(z+(.35gndlth,-.6gndlth)) withpen line;
853 addto GND doublepath (z+(-.2gndlth,-.7gndlth))--(z+(.2gndlth,-.7gndlth)) withpen line;
855 addto GND doublepath (z+(-.5gndlth,-.5gndlth))--(z+(.5gndlth,-.5gndlth))
856 withpen pencircle scaled 2linewd;
858 draw GND rotatedaround(z,ang);
861 newinternal junctiondiam;
864 vardef junction@#(expr z,name)(suffix $)=
866 draw z withpen pencircle scaled junctiondiam;
867 label.$(latex(name),z);
870 vardef impedance@#(expr z,ang,name,val)=
872 pair Z@#.l, Z@#.r; % pines %
874 Z@#.r=(z+(1.5implth,0)) rotatedaround(z,ang);
875 picture imp; imp=nullpicture;
877 addto imp doublepath z--(z+(.25implth,0));
878 addto imp doublepath (z+(.25implth,-.18implth))--(z+(.25implth,.18implth))
879 --(z+(1.25implth,.18implth))--(z+(1.25implth,-.18implth))--cycle;
880 addto imp doublepath (z+(1.25implth,0))--(z+(1.5implth,0));
882 draw imp rotatedaround(z,ang) withpen line;
884 putlabel(Z@#.l,Z@#.r,.2implth,.2implth,ang,name,val);
889 int illuminating = 1;
891 TwoTerminal lamp(pair beg=(0,0), real ang=0, int type=normal,
892 string name="", string val="", bool draw=true)
894 real r = 0.5*circle_size;
898 term = _two_terminal_circle(beg=beg, ang=ang, name=name, val=val);
901 term.pLine.push((c - r*dir(45)) -- (c + r*dir(45)));
902 term.pLine.push((c - r*dir(-45)) -- (c + r*dir(-45)));
903 } else if (type==illuminating) {
904 term.pLine.push((c - (r,0)) -- (c - (r/2,0)));
905 term.pLine.push((c + (r/2,0)) -- (c + (r,0)));
906 term.pLine.push(shift(c)*scale(r/2)*(E..N..W));
915 //%%<--- Mesh current (corriente de malla) --->%%%
920 def imesh(expr c,wd,ht,dire,ang,name)=
921 save im,r; picture im; numeric r;
922 ahlength=3platsep; ahangle=20;
923 if ht > wd: r=.2wd elseif ht < wd: r=.2ht fi;
926 addto im doublepath (xpart c - .5wd, ypart c - .5ht)
927 --(xpart c - .5wd, ypart c + .5ht-r){up}
928 ..{right}(xpart c - .5wd + r, ypart c + .5ht)
929 --(xpart c + .5wd - r, ypart c + .5ht){right}
930 ..{down}(xpart c + .5wd,ypart c + .5ht - r)
931 --(xpart c + .5wd,ypart c - .5ht + r){down}
932 ..{left}(xpart c + .5wd - r,ypart c - .5ht)
933 --(xpart c - .25wd, ypart c - .5ht);
934 addto im contour arrowhead (xpart c - .5wd, ypart c - .5ht)
935 --(xpart c - .5wd, ypart c + .5ht-r){up}
936 ..{right}(xpart c - .5wd + r, ypart c + .5ht)
937 --(xpart c + .5wd - r, ypart c + .5ht){right}
938 ..{down}(xpart c + .5wd,ypart c + .5ht - r)
939 --(xpart c + .5wd,ypart c - .5ht + r){down}
940 ..{left}(xpart c + .5wd - r,ypart c - .5ht)
941 --(xpart c - .25wd, ypart c - .5ht);
943 addto im doublepath (xpart c + .5wd, ypart c - .5ht)
944 --(xpart c + .5wd, ypart c + .5ht-r){up}
945 ..{left}(xpart c + .5wd - r, ypart c + .5ht)
946 --(xpart c - .5wd + r, ypart c + .5ht){left}
947 ..{down}(xpart c - .5wd,ypart c + .5ht - r)
948 --(xpart c - .5wd,ypart c - .5ht + r){down}
949 ..{right}(xpart c - .5wd + r,ypart c - .5ht)
950 --(xpart c + .25wd, ypart c - .5ht);
951 addto im contour arrowhead (xpart c + .5wd, ypart c - .5ht)
952 --(xpart c + .5wd, ypart c + .5ht-r){up}
953 ..{left}(xpart c + .5wd - r, ypart c + .5ht)
954 --(xpart c - .5wd + r, ypart c + .5ht){left}
955 ..{down}(xpart c + .5wd,ypart c + .5ht - r)
956 --(xpart c - .5wd,ypart c - .5ht + r){down}
957 ..{right}(xpart c - .5wd + r,ypart c - .5ht)
958 --(xpart c + .25wd, ypart c - .5ht);
961 if labeling=rotatelabel:
962 addto im also thelabel(latex("$" & name & "$"),c);
963 elseif labeling=norotatelabel:
964 addto im also thelabel(latex("$" & name & "$") rotatedaround(c,-ang),c);
967 draw im rotatedaround (c,ang) withpen line;
970 //%%<--- Reostatos --->%%%
972 newinternal rheolth, Rrheo, Lrheo;
973 rheolth=2mm; Rrheo=1; Lrheo=2;
975 vardef rheostat@#(expr z,type,ang)=
976 save reo; picture reo; reo=nullpicture;
977 pair rh@#.i, rh@#.s, rh@#.r;
978 rh@#.i=z; rh@#.s=(z+(0,6rheolth)) rotatedaround(z,ang);
979 rh@#.r=(z+(3rheolth,6rheolth)) rotatedaround(z,ang);
981 ahangle=20; ahlength=rheolth;
984 addto reo doublepath (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
985 --(z+(4rheolth,-.7rheolth));
986 addto reo contour arrowhead (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
987 --(z+(4rheolth,-.9rheolth));
989 addto reo doublepath z--(z+(rheolth,0)){down}.. for i=2 upto 4:
990 {up}(z+(i*rheolth,0)){down}.. endfor {up}(z+(5rheolth,0))--(z+(6rheolth,0));
992 reo=reo rotatedaround(z,90);
994 addto reo doublepath (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
995 --(z+(4rheolth,-.7rheolth));
996 addto reo contour arrowhead (z+(6rheolth,-3rheolth))--(z+(4rheolth,-3rheolth))
997 --(z+(4rheolth,-.9rheolth));
999 addto reo doublepath z--(z+(1.5rheolth,0))--(z+(1.75rheolth,.75rheolth))--
1000 for i=.5 step .5 until 2.5: (z+((1.75+i)*rheolth,((-1)**(2i))*.75rheolth))--
1001 endfor (z+(4.5rheolth,0))--(z+(6rheolth,0)) withpen line;
1003 reo=reo rotatedaround(z,90);
1005 draw reo rotatedaround(z,ang) withpen line;
1010 // Loop symbols for Kirchhoff's rules.
1012 void kirchhoff_loop(picture pic=currentpicture, pair points[],
1013 pen outline=kirchhoff_pen, real aspace=-1) {
1014 // draw kirchhoff loop underneath currentpicture
1018 pair a = points[0] - points[points.length-1]; // arrow distance
1020 aspace = 3*linewidth(outline); // one dot diameter
1021 real alength = max(0.5*length(a), length(a) - aspace - linewidth(outline)/2);
1022 a = alength*unit(a);
1023 pair astop = points[points.length-1] + a;
1024 dot(newpic, points[0], scale(3)*outline);
1025 for (int i=0; i < points.length; ++i)
1028 draw(newpic, g, outline, Arrow(size=3*linewidth(outline)));
1029 add(pic, newpic, above=false);