Add LabeledCircle to Mechanics.asy and base Mass and Charge off of it.
authorW. Trevor King <wking@drexel.edu>
Wed, 11 Apr 2012 15:45:25 +0000 (11:45 -0400)
committerW. Trevor King <wking@drexel.edu>
Wed, 11 Apr 2012 15:45:36 +0000 (11:45 -0400)
This makes label handling easy and consistent (I've also left more
label processing to the Label itself).  Unfortunately, I can't figure
out how to make subclasses in Asymptote, so you'll have to update your
code to access the parameters that moved into LabeledCircle.  There
are new .center() and .set_center() methods to future proof you
against further changes to the location of that parameter.

asymptote/ElectroMag-test.asy
asymptote/ElectroMag.asy
asymptote/Mechanics-test.asy
asymptote/Mechanics.asy

index c2f5c0c5ca7271daaf8b2ab9811d0622bbd4f938..cac334af35b622fdc303c0df323762dd3a8bb9af 100644 (file)
@@ -25,11 +25,13 @@ Charge a = pCharge(center=(0.5u,2u));
 Charge b = aCharge(center=(0,0), q=1);
 Charge c = nCharge(center=(-3u,0), q=-3);
 Charge cs[] = {a,b,c};
-Distance dab = Distance(b.center, a.center, scale=u, L="$r_1$");
-Distance dbc = Distance(c.center, b.center, scale=u, L="$r_2$");
+Distance dab = Distance(b.center(), a.center(), scale=u, L="$r_1$");
+Distance dbc = Distance(c.center(), b.center(), scale=u, L="$r_2$");
 Distance ds[] = {dab};
-Angle abc = Angle(a.center, b.center, c.center, radius=.5u, L="$\theta_T$");
-Angle bac = Angle(b.center, a.center, c.center, radius=-0.4u, L="$\phi_x$");
+Angle abc = Angle(
+    a.center(), b.center(), c.center(), radius=.5u, L="$\theta_T$");
+Angle bac = Angle(
+    b.center(), a.center(), c.center(), radius=-0.4u, L="$\phi_x$");
 Angle as[] = {abc, bac};
 
 //write(a.center.x);
@@ -47,9 +49,9 @@ CoulombForces(c=cs, scale=2u, unit=u);
 
 Charge a = aCharge(center=(-2u, 2u), q=0);
 a.draw();
-Vector v = EField(a.center, mag=u/2, dir=0,L="E"); v.draw();
-Vector v = BField(a.center, mag=u/2, dir=90,L="B"); v.draw();
-Vector v = Velocity(a.center, mag=u/2, dir=180,L="$v$"); v.draw();
+Vector v = EField(a.center(), mag=u/2, dir=0,L="E"); v.draw();
+Vector v = BField(a.center(), mag=u/2, dir=90,L="B"); v.draw();
+Vector v = Velocity(a.center(), mag=u/2, dir=180,L="$v$"); v.draw();
 
 Vector Ic = Current(center=(-0.7u, 2.2u), phi=90, L="$I$"); Ic.draw();
 draw(shift(Ic.center)*scale(16pt)*unitcircle, BFieldPen, ArcArrow);
index 2efcb9350531841aee227a5dbcb4edf906d98e40..0e962aa6f786c373d592cc4e831a702dbcbe07ff 100644 (file)
@@ -25,67 +25,56 @@ import Mechanics;
 
 // charged particle
 struct Charge {
-  pair center;
+  LabeledCircle lc;
   real q;
-  real radius;
-  pen outline;
-  pen fill;
-  Label L;
   
-  void operator init(pair center=(0,0), real q=1, real radius=2mm, pen outline=currentpen, pen fill=red, Label L="") {
-    this.center = center;
+  void operator init(pair center=(0,0), real q=1, real radius=2mm,
+                     pen outline=currentpen, pen fill=red, Label label="") {
+    this.lc.operator init(center=center, radius=radius, outline=outline,
+                          fill=fill, label=label);
     this.q = q;
-    this.radius = radius;
-    this.outline = outline;
-    this.fill = fill;
-    this.L = L;
-  }
-  
-  void draw(picture pic=currentpicture) {
-    picture picF;
-    picture picL;
-    label(picL, L);
-    pair pLabelSize = 1.2 * (max(picL)-min(picL));
-    path c = scale(radius)*unitcircle;
-    filldraw(picF, c, fill, outline);
-    label(pic = picF,
-         L = L,
-         position = (0,-(radius+pLabelSize.y/2)));
-    add(pic, picF, center);
   }
+
+  pair center() { return this.lc.center; }
+  void set_center(pair center) { this.lc.center = center; }
+  void draw(picture pic=currentpicture) = this.lc.draw;
 }
 
 // positive charge
-Charge pCharge(pair center=(0,0), real q=1, real radius=2mm, pen outline=currentpen, Label L="")
+Charge pCharge(pair center=(0,0), real q=1, real radius=2mm,
+               pen outline=currentpen, Label label="")
 {
-  Charge c = Charge(center=center, q=q, radius=radius, outline=outline, L=L, fill=red);
-  return c;
+  return Charge(center=center, q=q, radius=radius, outline=outline, fill=red,
+                label=label);
 }
 
 // negative charge
-Charge nCharge(pair center=(0,0), real q=-1, real radius=2mm, pen outline=currentpen, Label L="")
+Charge nCharge(pair center=(0,0), real q=-1, real radius=2mm,
+               pen outline=currentpen, Label label="")
 {
-  Charge c = Charge(center=center, q=q, radius=radius, outline=outline, L=L, fill=blue);
-  return c;
+  return Charge(center=center, q=q, radius=radius, outline=outline, fill=blue,
+                label=label);
 }
 
 // neutral charge
-Charge neutralCharge(pair center=(0,0), real radius=2mm, pen outline=currentpen, Label L="")
+Charge neutralCharge(pair center=(0,0), real radius=2mm,
+                     pen outline=currentpen, Label label="")
 {
-  Charge c = Charge(center=center, q=0, radius=radius, outline=outline, L=L, fill=grey);
-  return c;
+  return Charge(center=center, q=0, radius=radius, outline=outline, fill=grey,
+                label=label);
 }
 
 // auto-signed charge
-Charge aCharge(pair center=(0,0), real q=1, real radius=2mm, pen outline=currentpen, Label L="")
+Charge aCharge(pair center=(0,0), real q=1, real radius=2mm,
+               pen outline=currentpen, Label label="")
 {
   Charge c;
   if (q > 0) {
-    c = pCharge(center, q, radius, outline, L);
+    c = pCharge(center, q, radius, outline, label);
   } else if (q < 0) {
-    c = nCharge(center, q, radius, outline, L);
+    c = nCharge(center, q, radius, outline, label);
   } else {
-    c = neutralCharge(center, radius, outline, L);
+    c = neutralCharge(center, radius, outline, label);
   }
   return c;
 }
@@ -121,11 +110,11 @@ Vector Current(pair center=(0,0), real mag=5mm, real dir=0, real phi=0, Label L=
 // Force of a on b
 Vector CoulombForce(Charge a, Charge b, Label L="", real scale=1mm, real unit=1mm)
 {
-  pair r = b.center - a.center;
+  pair r = b.center() - a.center();
   real mag, dir;
   mag = ((a.q*b.q)*(scale/length(r))^2)*unit;
   dir = degrees(r);
-  Vector v = Force(center=b.center, mag=mag, dir=dir, L=L);
+  Vector v = Force(center=b.center(), mag=mag, dir=dir, L=L);
   return v;
 }
 
index efd2cd5690d1cfb8ac1217a6008391b2c9e7e0b7..e6d5b3a78c04aa199f0f9d4270024448d4735116 100644 (file)
@@ -21,16 +21,38 @@ import Mechanics;
 
 real u = 1cm;
 
+LabeledCircle lc = LabeledCircle(center=(-2u, 1u));
+lc.draw();
+lc.label = "a";
+lc.center = (-2u, 0.5u);
+lc.draw();
+lc.draw_label(label=Label("e", align=E));
+lc.center = (-2u, 0);
+lc.label.align = W;
+lc.draw();
+lc.draw_label(label="b");
+lc.draw_label(label=Label("c", align=E));
+lc.draw_label(label=rotate(90)*Label("e------I", align=S));
+lc.draw_label(label=rotate(45)*Label("e------I", align=S));
+lc.center = (-2u, -2u);
+lc.radius = u/2;
+lc.label.align = E;
+lc.draw();
+lc.center = (-2u, -3u);
+lc.label.align = E;
+lc.draw();
+
 Mass a = Mass(center=(0,0));
 Mass b = Mass(center=(2u,1u));
 Mass c = Mass(center=(1u,-2u));
 Mass ms[] = {a,b, c};
-Distance dab = Distance(a.center, b.center, scale=u, L="$r_{ab}$");
-Distance dac = Distance(a.center, c.center, scale=u, L="$r_{ac}$");
+Distance dab = Distance(a.center(), b.center(), scale=u, L="$r_{ab}$");
+Distance dac = Distance(a.center(), c.center(), scale=u, L="$r_{ac}$");
 Distance ds[] = {dab, dac};
 Angle bac1 = Angle(
-    b.center, a.center, c.center, radius=.7u, fill=red, L="$\theta_T'$");
-Angle bac2 = Angle(b.center, a.center, c.center, radius=-.5u, L="$\theta_T$");
+    b.center(), a.center(), c.center(), radius=.7u, fill=red, L="$\theta_T'$");
+Angle bac2 = Angle(
+    b.center(), a.center(), c.center(), radius=-.5u, L="$\theta_T$");
 Angle as[] = {bac1, bac2};
 
 Vector vs[];
@@ -54,9 +76,11 @@ for (int i=0; i<vs.length; i+=1)
 Pendulum p = makePendulum(pivot=(3.5u,-3u), mass=b, length=4u, angleDeg=-20,
                           angleL="$\rho$", stringL="r");
 
-real len = abs(p.pivot.x-b.center.x);
-Spring s = Spring(pFrom=b.center-(2u,0), pTo=b.center, L="$k_1$");  s.draw();
-s = Spring(pFrom=b.center, pTo=(p.pivot.x, b.center.y), L="$k_2$"); s.draw();
+real len = abs(p.pivot.x-b.center().x);
+Spring s = Spring(pFrom=b.center()-(2u,0), pTo=b.center(), L="$k_1$");
+s.draw();
+s = Spring(pFrom=b.center(), pTo=(p.pivot.x, b.center().y), L="$k_2$");
+s.draw();
 
 p.draw(drawVertical=true);
 
index 6a634f4540f295a3df2b7e13374fc8a72e18a4c5..841414c3c3ee1fef7737dbc7f53c94d525d12a94 100644 (file)
 
 import geometry;
 
-// ---------------------- Mass -------------------------
+// ----------------- Labeled circle --------------------
 
-struct Mass {
+struct LabeledCircle {
   pair center;
-  real m;
   real radius;
   pen outline;
   pen fill;
-  Label L;
-  
-  void operator init(pair center=(0,0), real m=1, real radius=2mm, pen outline=currentpen, pen fill=grey, Label L="") {
+  Label label;
+
+  void operator init(pair center=(0,0), real radius=2mm,
+                     pen outline=currentpen, pen fill=grey, Label label="") {
     this.center = center;
-    this.m = m;
     this.radius = radius;
     this.outline = outline;
     this.fill = fill;
-    this.L = L;
+    this.label = label;
   }
-  
+
+  void draw_label(picture pic=currentpicture, Label label=null) {
+    picture picL;
+    align a;
+    if (label == null) {
+      label = this.label;
+    }
+    a = label.align;
+    if (label.align != NoAlign && label.align != Align) {
+      real m = labelmargin(label.p);
+      real scale = (m + this.radius)/m;
+      if (label.align.is3D) {
+        label.align.dir3 *= scale;
+      } else {
+        label.align.dir *= scale;
+      }
+    }
+    label(pic=pic, L=label, position=this.center);
+    label.align = a;
+  }
+
   void draw(picture pic=currentpicture) {
-    picture picF;
-    path c = scale(radius)*unitcircle;
-    filldraw(picF, c, fill, outline);
-    label(pic=picF, L=L, position=(0,0));
-    add(pic, picF, center);
+    path p = shift(this.center)*scale(this.radius)*unitcircle;
+    filldraw(pic, p, this.fill, this.outline);
+    this.draw_label(pic=pic);
   }
 }
 
+// ---------------------- Mass -------------------------
+
+struct Mass {
+  LabeledCircle lc;
+  real m;
+  
+  void operator init(pair center=(0,0), real m=1, real radius=2mm,
+                     pen outline=currentpen, pen fill=grey, Label label="") {
+    this.lc.operator init(center=center, radius=radius, outline=outline,
+                          fill=fill, label=label);
+    this.m = m;
+  }
+  
+  pair center() { return this.lc.center; }
+  void set_center(pair center) { this.lc.center = center; }
+  void draw(picture pic=currentpicture) = this.lc.draw;
+}
+
 struct Block {
   pair center;
   real m;
@@ -521,14 +556,14 @@ struct Pendulum {
   void operator init(pair pivot=(0,0), Mass mass=Mass()) {
     this.pivot = pivot;
     this.mass = mass;
-    this.angle = Angle(mass.center, pivot, pivot-(0,1));
-    this.str = Wire(pivot, mass.center);
+    this.angle = Angle(mass.center(), pivot, pivot-(0,1));
+    this.str = Wire(pivot, mass.center());
   }
   
   void draw(picture pic=currentpicture, bool drawVertical=false) {
     str.draw(pic=pic, rotateLabel=false);
     if (drawVertical == true) {
-      pair final = pivot + realmult((0,0.5),(mass.center-pivot));
+      pair final = pivot + realmult((0,0.5),(mass.center()-pivot));
       draw(pic=pic, pivot--final, p=currentpen+dashed);
     }
     draw(pic=pic, pivot);
@@ -539,7 +574,7 @@ struct Pendulum {
 
 // The angle argument is deflection from straight down (i.e. 0 degrees = plumb)
 Pendulum makePendulum(pair pivot=(0,0), Mass mass=Mass(), real length=15mm, real angleDeg=0, Label angleL="", Label stringL="") {
-  mass.center = pivot + length*dir(angleDeg-90);
+  mass.set_center(pivot + length*dir(angleDeg-90));
   Pendulum p = Pendulum(pivot=pivot, mass=mass);
   p.angle.L = angleL;
   p.str.L = stringL;