# vectors with marks for forces representation

In the first approach to teaching forces are presented to students diagrams with various forces and asked to them to group the forces according to their orientation, direction and magnitude. I often use this code, but would like to simplify it, correct the orientation of the labels and adjust the lengths of the vectors that are not multiples of the reference (my variable name: escala).

\starttext

\startMPcode
path p;
numeric t, escala;
pair OLD, NEW;
OLD:=(1.23433,3.46578634);
escala:=10; %% scale
def vector(expr A, B,ve)=
p := A..B;
for i = 0 upto 50:
t := escala*i/arclength(p);
NEW := point t of p;
if NEW <>OLD:
draw ((-2,0)--(2,0))
rotated (angle direction t of p-90)
shifted (point t of p)
withpen pencircle scaled .5pt withcolor red;
fi;
OLD:=point t of p;
endfor;
drawarrow p  withpen pencircle scaled 1pt withcolor .625red;
label.lft(textext ( ve ), point 0.5 of p);
enddef;

def reference(expr A, B,ve)=
p := A..B;
for i = 0 upto 50:
t := escala*i/arclength(p);
NEW := point t of p;
if NEW <>OLD:
draw ((-2,0)--(2,0)) rotated (angle direction t of p-90) shifted (point t of p)  withpen pencircle scaled .5pt withcolor red;
fi;
OLD:=point t of p;
endfor;
draw p  withpen pencircle scaled 1pt withcolor .625red;
label.top(ve, point 0.5 of p);
enddef;

vector((2cm,5cm),(4cm,5cm),"$\vec{F}_1$");
vector(origin,(0cm,5cm),"$\vec{F}_2$");
vector((2cm,2cm),(4cm,4cm),"$\vec{F}_3$");
vector((2cm,1cm),(7cm,1cm),"$\vec{F}_4$");
reference((5cm,3cm),(6cm,3cm), "3 N");
\stopMPcode

\stoptext


You code seems simplified enough to me as it is now, though I'm not sure to understand what you wish about adjusting lengths. As for the labels, I would suggest to use the freelabel macro of Metafun, that is to say, to replace the line

label.lft(textext ( ve ), point 0.5 of p);

in your vector definition by something like that:

pair lpoint ; lpoint = point 0.5 of p;
freelabel(ve, lpoint, lpoint + (A-B) rotated 90);


See the MetaFun manual (p. 274) for more details about this most useful macro. The results is as follows:

Edit for length adjusting, I've finally changed the vector definition by introducing the numeric variable N = floor(arclength p / escala) which gives the number of subdivisions, and replaced the instruction

drawarrow p  withpen pencircle scaled 1pt withcolor .625red;


by

drawarrow A -- (point N*escala on p)  withpen pencircle scaled 1pt withcolor .625red;


The new vector definition:

def vector(expr A, B,ve)=
p := A..B;
numeric N ; N = floor(arclength(p)/escala) ;
for i = 0 upto N :
t := escala*i/arclength(p);
draw ((-2,0)--(2,0)) rotated (angle direction t of p-90)
shifted (point t of p)
withpen pencircle scaled .5pt withcolor red;
endfor;
drawarrow A -- (point N*escala on p)  withpen pencircle scaled 1pt withcolor .625red;
pair lpoint ; lpoint = point 0.5 of p;
freelabel(ve, lpoint, lpoint + (A-B) rotated 90);
enddef;


The new result:

Note that the arrows go very slightly beyond the last marks, because of the pen thickness chosen to draw the lines. If you want to avoid that, either reduce this thickness or increase the marks' one.

• Thanks for your support. About the adjusting the vector length, see, for example, the $\vec{F}_4$ where the magnitude is 14 N + a decimal number. I want to cut the vector at exactly 14 N. I know that i can fix this lengths by hand, but I would like to generated random vectors. – Jorge Jan 23 '15 at 16:42
• OK, I understand now. I've added a way to do that in my answer. – Franck Pastor Jan 23 '15 at 19:24