How to extend the segments [II'], [JJ'] and [AA'] as in the figure ?

enter image description here

  numeric u;
  u = 10mm;

  pickup pencircle scaled 1pt;

  angle_radius := 8pt;

  def mark_rt_angle (expr a, b, c, d) =
     fill ((1,0)--(1,1)--(0,1)--origin--cycle)
     zscaled (angle_radius*unitvector(a-b))
     shifted b withcolor d;
     draw ((1,0)--(1,1)--(0,1))
     zscaled (angle_radius*unitvector(a-b)) shifted b;

  % macro drawing a circular arc (Franck Pastor)

  vardef arc(expr theta_min, theta_max) =
    save theta, mystep ; 
    mystep = 1; theta = theta_min ;
    dir theta_min 
    for theta = theta_min+mystep step mystep until theta_max:
    .. dir theta endfor 

   z1=z0 rotated 90;
   z2=z1 rotated 120;
   z3=z2 rotated 120;
   z5=z3 rotatedaround (z2,180);
   z6=z3 rotatedaround (z2,90);
   z7=z3 rotatedaround (z2,-90);

   path triangle; triangle = z1--z2--z3--cycle;
   theta_min := 0;
   theta_max := 60;
   pair center; center = origin;
   r := 0.5u; 
   myeps := 0.25u ; path p, a, b;
   a = (center -- center + dir theta_min) scaled r shifted z2;
   b = (center -- center + dir theta_max) scaled r shifted z2;
   p = arc(theta_min, theta_max) scaled (r) shifted z2;

  fill b -- a -- p -- cycle withcolor green;
  fill triangle withcmykcolor(0.00,0.03,0.44,0.2);
  fill b -- a -- p -- cycle withcmykcolor (1,0.00,1,0.07);
  mark_rt_angle (z3, z4, z1, green);
  draw z1--z4 withcolor blue;
  draw fullcircle scaled 2abs(z3-z2) shifted z2;
  draw z6 -- z7;
  draw z3 -- z5;
  draw triangle withpen pencircle scaled 1.5bp withcmykcolor(0,0.5,0.69,0);
  draw z1 withpen pencircle scaled 4bp withcolor red;
  draw z4 withpen pencircle scaled 4bp withcolor red;

  label.bot(btex $A'$ etex,z4);
  label.llft(btex $O$ etex,z2);
  label.rt(btex $I$ etex,z3);
  label.top(btex $A$ etex,z1);
  label.lft(btex $I'$ etex,z5);
  label.top(btex $J$ etex, z6);
  label.bot(btex $J'$ etex, z7);


You can set the format to MetaFun in which case you get access to the shortened path operation. When using a negative length for shortenend the path will extend rather than be trimmed.

I took the liberty to shorten and clean up your code a little.

    % Definitions
    numeric u; u = 10mm;

    pair O ; O := origin ;
    pair A ; A := (2u, sqrt(3)*2u) ;
    pair Aprime ; Aprime := (xpart A, ypart O) ;

    % Determine radius
    numeric r ; r := arclength (O -- A) ;
    pair I ; I := (r, ypart O) ;

    % Axes
    draw (-I -- O -- I) shortened -.5u ;
    draw (-I -- O -- I) shortened -.5u rotated 90 ;

    % Enclosing circle
    draw fullcircle scaled (2*r) ;

    % Triangle (only fill)
    path triangle ; triangle := O -- A -- I -- cycle ;
    fill triangle withcmykcolor(0.00,0.03,0.44,0.2) ;

    % Angle
    path arc ; arc := O -- anglebetween(O -- I, O -- A, " ") -- cycle ;
    fill arc withcolor green ;
    draw arc withcmykcolor (1,0.00,1,0.07) ;

    % Right angle
    draw image (
        fill unitsquare scaled .5u withcolor green ;
        draw unitsquare scaled .5u withcmykcolor (1,0.00,1,0.07) ;
    ) shifted Aprime ;
    draw (A -- Aprime) shortened -1cm withcolor blue ;

    % Draw triangle
    draw triangle withpen pencircle scaled 1.5bp withcmykcolor(0,0.5,0.69,0) ;

    % Mark A and A' with dots
    picture dot ; dot := image (
        fill fullcircle scaled 4pt withcolor red ;
        draw fullcircle scaled 4pt withcolor white ;
    ) ;
    draw dot shifted A ;
    draw dot shifted Aprime ;

    % Labels
    label.llft("$O$", O) ;
    label.lrt("$I$", I) ;
    label.llft("$I'$", -I) ;
    label.ulft("$J$", I rotated 90) ;
    label.urt("$A$", A) ;
    label.lrt("$A'$", Aprime) ;

enter image description here

| improve this answer | |
  • Thank you for this elegant code. – Fabrice Oct 2 '19 at 21:55

Just for fun an alternative with TikZ. At least superficially this appears to be shorter and simpler than the MetaPost code.

\begin{tikzpicture}[declare function={R=3;}]
 \draw[thick] (0,0) coordinate (O) circle[radius=R] 
  (-R,0) coordinate[label=below left:$I'$] (I') 
  (R,0)  coordinate[label=below right:$I$] (I)  
  (0,R) coordinate[label=above left:$J$] (J)
  (0,-R) coordinate[label=below left:$J'$] (J');
 \draw[shorten >=-1em,shorten <=-1em,thick]  (I) -- (I');
 \draw[shorten >=-1em,shorten <=-1em,thick]  (J) -- (J');
 \draw[red,fill=red!30] (0,0) -- (60:R) coordinate (A)  -- (I) -- cycle
  coordinate[midway] (A');
 \pic[draw=green!70!black, fill=green, angle radius=6mm]{angle=I--O--A};
 \draw[thick,blue] (A|-0,R*1cm+1em) -- (A|-0,-R*1cm-1em); 
 \path pic[draw=green!70!black, fill=green, angle radius=4mm]{right angle=I--A'--A}
  (A) node[circle,inner sep=1pt,fill=red,label=above right:$A$]{}
  (A') node[circle,inner sep=1pt,fill=red,label=below right:$A'$]{};

enter image description here

| improve this answer | |
  • I'm not sure whether this is much shorter than the equivalent MetaPost variant. Sure, I can also cram everything into a single line and claim it is shorter. – Henri Menke Oct 2 '19 at 1:56
  • @HenriMenke As I can see, you succeeded. Congrats! 🍾🎈🎊🎉 – user194703 Oct 2 '19 at 2:11

To focus on just the specific question of "expanding" a line segment....

In your particular diagram, if you centre the circle on the origin, then you can use a simple scale operation to make a longer line, so if you define your main circle as

path C; C = fullcircle scaled 200;

then to get your extended line through I and I' you could try:

draw (point 0 of C -- point 4 of C) scaled 1.1;

but this relies on C being centred on the origin. So to be more general, you would have to write something cumbersome like

draw (point 0 of C -- point 4 of C) shifted - center C scaled 1.1 shifted center C;

which could be worse, if the rules of precedence were not so well designed.

If on the other hand, you already have two points z0 and z1 and you want to extend a segment through both points, you can use the mediation syntax like this:

draw (-0.1)[z0, z1] -- 1.1[z0, z1];

this draws a straight line from a point 10% "before" z0 to a point 10% "after" z1. If the idea of negative mediation offends you, then you can just swap the order of the points:

draw 1.1[z1, z0] -- 1.1[z0, z1];

Finally since the others have had a go at re-drawing your code, here is another effort for comparison (compile with lualatex). Note that you can change it just by changing the size of the circle and the value of p. Everything else should be calculated relative to those.

    path C, T, arc, sq, xx, yy;
    C = fullcircle scaled 140;

    numeric p;
    p = 4/3;
    T = origin -- point 0 of C -- point p of C -- cycle;
    arc = origin -- subpath (0, p) of fullcircle scaled 20 -- cycle;
    sq = unitsquare scaled 6 shifted (xpart point p of C, 0);

    xx = (point 4 of C -- point 0 of C) scaled 1.1;
    yy = (point 6 of C -- point 2 of C) scaled 1.1;

    color pink, forest, royal;

    pink = (3/4, 1/3, 1/3);
    forest = (1/3, 2/3, 1/4);
    royal = (1/3, 1/3, 2/3);

    fill T withcolor 1/2[pink, white];

    fill sq  withcolor 1/2[forest, white]; draw sq  withcolor forest;
    fill arc withcolor 1/2[forest, white]; draw arc withcolor forest;

    draw T withcolor pink;

    draw xx;
    draw yy;
    draw C withpen pencircle scaled 3/4;

    draw yy shifted point 0 of sq withcolor royal;

    label.llft("$O$", origin);
    label.lrt("$I$", point 0 of C);
    label.ulft("$J$", point 2 of C);
    label.llft("$I'$", point 4 of C);

    label.urt("$A$", point p of C);
    label.lrt("$A'$", (xpart point p of C, 0));

    fill fullcircle scaled dotlabeldiam shifted point p of C withcolor 2/3 red;
    draw fullcircle scaled dotlabeldiam shifted point p of C withcolor white;

    fill fullcircle scaled dotlabeldiam shifted (xpart point p of C, 0) withcolor 2/3 red;
    draw fullcircle scaled dotlabeldiam shifted (xpart point p of C, 0) withcolor white;


enter image description here

| improve this answer | |
  • Thank you, nice code where I learn other possible approaches. – Fabrice Oct 4 '19 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.