6

I want to reproduce the image below with Metapost. I think this code is too long and the result is not exactly the expected one.

enter image description here

beginfig(1)
input hatching ;

hatchoptions (withcolor red);

path p, q, r, b ;
pair t[] ;
p := fullcircle scaled 6cm ;
q := fullcircle scaled 4cm shifted (2.5cm,2cm) ;
r := fullcircle scaled 4cm shifted (-2.5cm,2cm);
b := fullcircle scaled 2cm shifted (0,-3cm);

z1 = p intersectionpoint r ;
dotlabel.urt("1",z1) withcolor blue ;

t0 := p intersectiontimes r ;
p := subpath(xpart t0, infinity) of p ;
r := subpath(ypart t0, infinity) of r ;

z2 = p intersectionpoint r ;
dotlabel.urt("2",z2) withcolor red ;

z3 = p intersectionpoint q ;
dotlabel.urt("3",z3) withcolor magenta ;

t1 := p intersectiontimes q ;
p := subpath(xpart t1, infinity) of p ;
q := subpath(ypart t1, infinity) of q ;

z4 = p intersectionpoint q ;
dotlabel.ulft("4",z4) withcolor cyan ;

z5 = p intersectionpoint b ;
dotlabel.ulft("5",z5) withcolor magenta ;

t2 := p intersectiontimes b ;
p := subpath(xpart t2, infinity) of p ;
b := subpath(ypart t2, infinity) of b ;

z6 = p intersectionpoint b ;
dotlabel.urt("6",z6) withcolor red ;

hatchfill buildcycle(z1 .. point 2 of r .. point 4 of r .. z2, z2 .. point 6 of p .. z1) 
withcolor (-90, 2mm, -1bp) ;

hatchfill buildcycle(z3 .. point 2 of q .. point 4 of q .. z4,z4 .. point 4 of p .. z3) 
withcolor (-90, 2mm, -1bp) ;

hatchfill buildcycle(z1 .. point 8 of r .. point 7 of r .. point 6 of r ..
z2 .. point 7 of p .. point 8 of p .. z5 .. point 8 of b .. point 7 of b ..
z6 .. point 10 of p .. point 11 of p.. z3 .. point 8 of q .. point 7 of q ..
point 6 of q .. z4 .. point 5 of p .. z1) 
withcolor (-180, 2mm, -1bp) ;

hatchfill buildcycle(z6 .. point 3 of b .. z5,z5 .. point 9 of p .. z6) 
withcolor (-90, 2mm, -1bp) ;

draw p ;
draw q ;
draw r ;
draw b ;

endfig;

end

enter image description here

  • Also how exactly are you compiling this example? I get errors – daleif Feb 5 at 12:02
  • The last two buildcycles have the completely wrong shapes if you draw them instead of hatching them. You should probably build it using subpaths instead of doing it this way – daleif Feb 5 at 12:07
  • When I run your code, I also get that 5=6. – daleif Feb 5 at 12:10
  • I'm just starting to use Metapost and I compiled this file without any problem with context by including the file in this environment \startMPcode ... \stopMPcode – Fabrice Feb 6 at 10:13
  • When you are not using plain metapost, then please specify that. The context setup for metapost is differerent from plan metapost. – daleif Feb 6 at 10:16
7

You either need to create those boundary paths correctly (try drawing them instead of haching them (easy you define each of them to be a named path).

Here is a different method using unfill and clipping. Note the clip is needed to limit the effect of each unfill on a picture.

My system did not like magenta and cyan as named colors, so I used rgb instead.

beginfig(1);
input hatching ;


hatchoptions (withcolor red);

  path p, q, r, b ;
  pair t[] ;

  path pp[];

  picture pics[];


p := fullcircle scaled 6cm ;
q := fullcircle scaled 4cm shifted (2.5cm,2cm) ;
r := fullcircle scaled 4cm shifted (-2.5cm,2cm);
b := fullcircle scaled 2cm shifted (0,-3cm);

z1 = p intersectionpoint r ;
%dotlabel.urt("1",z1) withcolor blue ;

t0 := p intersectiontimes r ;
pp0 := subpath(xpart t0, infinity) of p ;
pp1 := subpath(ypart t0, infinity) of r ;

z2 = pp0 intersectionpoint r ;
%dotlabel.urt("2",z2) withcolor red ;

z3 = p intersectionpoint q ;
%dotlabel.urt("3",z3) withcolor green ;

t1 := p intersectiontimes q ;
pp2 := subpath(xpart t1, infinity) of p ;
pp3 := subpath(ypart t1, infinity) of q ;

  z4 = pp2 intersectionpoint q ;
%dotlabel.ulft("4",z4) withcolor green ;

z5 = p intersectionpoint b ;
%dotlabel.ulft("5",z5) withcolor green ;

t2 := p intersectiontimes b ;
pp4 := subpath(xpart t2+0.001, infinity) of p ;
pp5 := subpath(ypart t2, infinity) of b ;

z6 = pp4 intersectionpoint b ;
%dotlabel.urt("6",z6) withcolor red ;



  hatchfill p withcolor (-180, 2mm, -1bp) ;

  unfill b;
  unfill q;
  unfill r;

  clip currentpicture to p;
  pics1 := currentpicture;
  currentpicture := nullpicture;


  hatchfill r withcolor (-90, 2mm, -1bp) ;
  unfill p;

  clip currentpicture to r;
  pics2 := currentpicture;
  currentpicture := nullpicture;

  hatchfill q withcolor (-90, 2mm, -1bp) ;
  unfill p;

  clip currentpicture to q;
  pics3 := currentpicture;
  currentpicture := nullpicture;

  hatchfill b  withcolor (-90, 2mm, -1bp);
  unfill p;

  clip currentpicture to b;
  pics4 := currentpicture;
  currentpicture := nullpicture;



  draw pics1;
  draw pics2;
  draw pics3;
  draw pics4;



  draw p ;
  draw q ;
  draw r ;
  draw b ;

dotlabel.urt("1",z1) withcolor blue ;
dotlabel.urt("2",z2) withcolor red ;
dotlabel.urt("3",z3) withcolor green ;
dotlabel.ulft("4",z4) withcolor green ;
dotlabel.ulft("5",z5) withcolor green ;
dotlabel.urt("6",z6) withcolor red ;



endfig;

end

enter image description here

  • Thank you for this solution and for all explanations. – Fabrice Feb 6 at 10:22
5

Another way to simplify things...

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1)
input hatching

hatchoptions (withcolor red);

path face, left_ear, right_ear, mouth;
face      = fullcircle scaled 168;
right_ear = fullcircle scaled 112 shifted 96 right rotated 40;
left_ear  = fullcircle scaled 112 shifted 96 right rotated 140;
mouth     = fullcircle scaled  56 shifted 85 down; 

hatchfill face      withcolor ( 0, 6, -1); 
hatchfill left_ear  withcolor (90, 6, -1);
hatchfill right_ear withcolor (90, 6, -1);
hatchfill mouth     withcolor (90, 6, -1);

unfill buildcycle(face, mouth);
unfill buildcycle(face, left_ear);
unfill buildcycle(face, right_ear);

draw face;
draw left_ear;
draw right_ear;
draw mouth ;

endfig;
end

enter image description here

Notes

  • There's no shortage of pixels on my system, so I changed the names of the paths to things that were more obvious

  • I like working in points, so I am using points instead of cm. I find it easier to write things like 96 right instead of (3.4cm, 0).

  • I redefined the "ears" to be circles shifted right and then rotated instead of just shifted by (x, y). This turns out to be important because of a small issue with buildcycle. If you want it to work with two circles, it is important that neither circle starts inside the other one.

  • I've then used hatchfill to fill each of the shapes completely, and then unfilling the overlaps. Apart from the bug noted above, buildcycle is rather simpler to use than the OP had.

  • Thank you for this very clean solution. What do you mean by "OP originally" ? – Fabrice Feb 6 at 10:21
  • @Fabrice I've corrected my grammar. I have no idea why I put in an additional "originally"! I just meant to point out that buildcycle will do all the hard work for you. Just give it the paths and it will work out where the intersection points are (in most circumstances) – Thruston Feb 6 at 13:34

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.