Difference between revisions of "MetaPost"

From Wiki
Jump to navigation Jump to search
(Make clearer the MetaPost/MetaFun relation)
m (→‎Documentation & Tutorials: delete link to deleted wiki page)
(12 intermediate revisions by 5 users not shown)
Line 1: Line 1:
<  [[Math]], [[MetaFun]], [[Graphics]]
+
__TOC__
 
 
 
MetaPost is a graphical programming language, based on Donald Knuth's MetaFont. Normally MP graphics are converted to PostScript and used with dvips, but ConTeXt can use it directly with PDF (see the
 
MetaPost is a graphical programming language, based on Donald Knuth's MetaFont. Normally MP graphics are converted to PostScript and used with dvips, but ConTeXt can use it directly with PDF (see the
 
[http://www.pragma-ade.com/general/sources/mptopdf.pdf MP to PDF] manual).
 
[http://www.pragma-ade.com/general/sources/mptopdf.pdf MP to PDF] manual).
  
MetaPost is ConTeXt's native graphics language. [[MetaFun]] is a MetaPost module by Hans Hagen that adds a lot of extra features; it is enabled by default, so one could say that MetaFun is ConTeXt's default dialect of MetaPost.
+
MetaPost is ConTeXt's native graphics language. [[MetaFun - MetaPost in ConTeXt]] is a MetaPost module by Hans Hagen that adds a lot of extra features; it is enabled by default, so one could say that MetaFun is ConTeXt's default dialect of MetaPost.
  
== Documentation & Tutorials ==
+
= Documentation & Tutorials =
 
* [http://www.tug.org/docs/metapost/mpman.pdf A User's Manual for MetaPost] <!-- http://cm.bell-labs.com/who/hobby/cstr_162.pdf has its pages reversed -->
 
* [http://www.tug.org/docs/metapost/mpman.pdf A User's Manual for MetaPost] <!-- http://cm.bell-labs.com/who/hobby/cstr_162.pdf has its pages reversed -->
 
* [http://remote.science.uva.nl/~heck/Courses/mptut.pdf Learning METAPOST by doing] ([http://maps.aanhet.net/maps/pdf/32_14.pdf this] and [http://maps.aanhet.net/maps/pdf/32_15.pdf this link] are not working)
 
* [http://remote.science.uva.nl/~heck/Courses/mptut.pdf Learning METAPOST by doing] ([http://maps.aanhet.net/maps/pdf/32_14.pdf this] and [http://maps.aanhet.net/maps/pdf/32_15.pdf this link] are not working)
Line 12: Line 11:
 
* [[manual:metafun-s.pdf|MetaFun]]
 
* [[manual:metafun-s.pdf|MetaFun]]
 
* [http://tex.loria.fr/prod-graph/zoonekynd/metapost/metapost.html Lots of examples]
 
* [http://tex.loria.fr/prod-graph/zoonekynd/metapost/metapost.html Lots of examples]
 +
* [[Color in MetaPost]] describes how to get color mixtures, TeX colors, and transparent effects in MetaPost graphics.
  
 +
= Using MetaPost in ConTeXt =
  
== Troubleshooting plain MetaPost ==
+
With {{cmd|startuseMPgraphic}}, you define a piece of graphics code that is processed anew every time the graphic is placed with {{cmd|useMPgraphic}}. Further commands are described at [[MetaFun - MetaPost in ConTeXt]].
* Test if MetaPost is installed on your system.
+
 
* create test.mp containing this:
+
<context source=yes>
 +
\def\mycolor{.625red}
 +
 
 +
\startuseMPgraphic{name}
 +
  fill fullcircle scaled 20pt withcolor \mycolor;
 +
\stopuseMPgraphic
 +
 
 +
red: \useMPgraphic{name}
 +
 
 +
\def\mycolor{.625blue}
 +
blue: \useMPgraphic{name}
 +
</context>
 +
 
 +
= Different Packages, Extensions & Applications of Metapost =
 +
* [http://www.ctan.org/tex-archive/graphics/metaplot/ MetaPlot] - graph drawing
 +
* [http://www.ctan.org/tex-archive/graphics/metapost/contrib/macros/metaobj/ MetaObj] - object-oriented drawing, see also the page about [[MetaObj and Labels]]
 +
 
 +
* [http://stud4.tuwien.ac.at/~e0225855/finomaton/finomaton.html finomaton] - drawing finite state automata
 +
* [http://www-math.univ-poitiers.fr/~phan/statsmac.html statsmac] - metapost macros for statistics graphs
 +
* [http://metauml.sourceforge.net/ MetaUML] - MetaPost library for typesetting UML diagrams
 +
* [http://vigna.dsi.unimi.it/metagraph/ METAGRAPH] - drawing (un)directed graphs
 +
 
 +
== 3D support ==
 +
* [http://matagalatlante.org/nobre/featpost/doc/featexamples.html FeatPost]
 +
* [http://www.gnu.org/software/3dldf/LDF.html 3DLDF]
 +
* [http://www-math.univ-poitiers.fr/~phan/m3Dplain.html m3D]
 +
 
 +
{{todo|needs major review}}
 +
 
 +
= MetaPost relatives =
 +
== Font Creation ==
 +
* [[MetaType1]], see [http://www.ctan.org/tex-archive/fonts/utilities/metatype1/ CTAN]
 +
 
 +
== 3D drawing ==
 +
* [http://asymptote.sourceforge.net/ Asymptote] - inspired by MetaPost & fully generalizes MetaPost path construction algorithms to three-dimensions
 +
 
 +
= Testing plain MetaPost =
 +
To test whether MetaPost is installed on your system, create a file called {{code|test.mp}}:
  
 
  beginfig(1)
 
  beginfig(1)
Line 30: Line 68:
  
 
* that should create a postscript file test.1
 
* that should create a postscript file test.1
* open test.1 with a postscript viewer like ghostview, okular, … You should see a circle.
+
* open test.1 with a postscript viewer like Ghostview, Okular, … You should see a circle.
  
== Troubleshooting MetaPost embedded in ConTeXt ==
+
= Testing MetaPost embedded in ConTeXt =
  
* create test.tex containing this:
+
If MetaPost is installed on your system and working correctly, you can
  
 
  \starttext
 
  \starttext
Line 49: Line 87:
  
 
* that should create a pdf file test.pdf
 
* that should create a pdf file test.pdf
* open test.pdf with a pdf viewer like acroread, okular... You should see a circle.
+
* open test.pdf with a pdf viewer like Adobe Acrobat, Okular... You should see a circle.
 +
 
 +
= Text in MetaPost =
 +
 
 +
Text that is typeset using `textext` or `btex … etex` adapts to the body font. However, when `label("Foo", pair)` or `"Foo" infont defaultfont` is used, which is not the recommended way, the text is typeset using the font `MetafunDefault`, which can be changed if desired. Example:
 +
 
 +
<context mode="mkiv" source="yes" text="Gives:">
 +
\starttext
 +
  \startMPcode
 +
    label("Foo", origin);
 +
    draw textext("Bar") yshifted -LineHeight;
 +
  \stopMPcode
 +
 
 +
  \definefontsynonym
 +
    [MetafunDefault]
 +
    [Bold*default]
 +
 
 +
  \switchtobodyfont [pagella, 18pt]
 +
 
 +
  \startMPcode
 +
    label("Foo", origin);
 +
    draw textext("Foo") yshifted -LineHeight;
 +
  \stopMPcode
 +
\stoptext
 +
</context>
  
== Different Packages, Extensions & Applications of Metapost ==
+
The recommended way to typeset text is to use the `textext` macro and change the font using {{cmd |setupMPinstance}}.
* [http://www.ctan.org/tex-archive/graphics/metaplot/ MetaPlot] - graph drawing
+
 
* [http://www.ctan.org/tex-archive/graphics/metapost/contrib/macros/metaobj/ MetaObj] - object-oriented drawing, see also the page about [[MetaObj and Labels]]
+
= Repetition of a Text Element to Fill a Bar Using textext =
 +
 
 +
Imagine you want to create a frame which consists out of one glyph or a combination of different glyphs in order to make a decorative border. For this purpose a series of such elements should be placed on the bar as pictures, evenly spaced. Probably you want to have at the end of the bar a different glyph inserted as a picture too.
 +
 
 +
The following code is working but the last picture is not the expected glyph. One would expect 14 times the "?" and at the end of the bar a "*":
 +
 
 +
<context mode="mkiv" source="yes" text="Gives:">
 +
\starttext
 +
  \startMPpage
 +
      picture PicA ; PicA := textext("*");
 +
      picture PicB ; PicB := textext("?");
 +
 
 +
      numeric Step ; Step := 2cm div bbwidth(PicB)  ;
 +
 
 +
      for i = 1 upto Step :
 +
        draw PicB shifted (i*5mm,0) ;
 +
      endfor ;
 +
      draw PicA ;
 +
  \stopMPpage
 +
\stoptext
 +
</context>
 +
 
 +
What you get is 15 "?" but no "*"!
 +
 
 +
In order to get this corrected one needs to calculate the boundingbox of the "?" on beforehand. Hans Hagen provided this solution on 14-10-2014.
 +
 
 +
<context mode="mkiv" source="yes" text="Gives:">
 +
\starttext
 +
  \startMPcalculation
 +
      path PicX ; PicX := boundingbox textext("?") ;
 +
  \stopMPcalculation
 +
 
 +
  \startMPpage
 +
      picture PicA ; PicA := textext("*");
 +
      picture PicB ; PicB := textext("?");
 +
 
 +
      numeric Step ; Step := 2cm div bbwidth(PicX) ;
 +
      % numeric Step ; Step := 2cm div bbwidth(PicB)  ;
 +
 
 +
      for i = 1 upto Step :
 +
        draw PicB shifted (i*5mm,0) ;
 +
      endfor ;
 +
      draw PicA ;
 +
  \stopMPpage
 +
\stoptext
  
* [http://stud4.tuwien.ac.at/~e0225855/finomaton/finomaton.html finomaton] - drawing finite state automata
+
</context>
* [http://www-math.univ-poitiers.fr/~phan/statsmac.html statsmac] - metapost macros for statistics graphs
 
* [http://metauml.sourceforge.net/ MetaUML] - MetaPost library for typesetting UML diagrams
 
* [http://vigna.dsi.unimi.it/metagraph/ METAGRAPH] - drawing (un)directed graphs
 
  
=== 3D support ===
+
Now you get 14 "?" and the "*".
* [http://matagalatlante.org/nobre/featpost/doc/featexamples.html FeatPost]
 
* [http://www.gnu.org/software/3dldf/LDF.html 3DLDF]
 
* [http://www-math.univ-poitiers.fr/~phan/m3Dplain.html m3D]
 
  
{{todo|needs major review}}
+
== A Full Example ==
  
== MetaPost relatives ==
+
<context mode="mkiv" source="yes" text="Gives:">
=== Font Creation ===
+
\setupbodyfont [8pt]
* [[MetaType1]], see [http://www.ctan.org/tex-archive/fonts/utilities/metatype1/ CTAN]
 
  
=== 3D drawing ===
+
\defineoverlay[Myframe][\reuseMPgraphic{Frame}]
* [http://asymptote.sourceforge.net/ Asymptote] - inspired by MetaPost & fully generalizes MetaPost path construction algorithms to three-dimensions
 
  
== Using MP in ConTeXt ==
+
\setuppapersize[A8][A8]
The first way is a usable graphic. Such a graphic is calculated anew each time it is used. An example:
 
  
<texcode>
+
\setuplayout
\startuseMPgraphic{name}
+
  [topspace=5mm,
  fill fullcircle scaled 5cm withcolor red;
+
    backspace=5mm,
\stopuseMPgraphic
+
    height=middle,
 +
    width=middle,
 +
    header=0pt,
 +
    footer=0pt]
  
\useMPgraphic{name}
+
\starttext
</texcode>
 
  
As said, this graphic is calculated each time it is placed, which can be time consuming. Apart from the time aspect, this also means that the graphic itself is incorporated many times. Therefore, for graphics that don’t change, CONTEXT provides reusable graphics:
+
% ======== Definition of the frame in Metafun ==========
 +
\startMPcalculation
 +
  path PicX ; PicX := boundingbox textext("= : =") ;
 +
\stopMPcalculation
 +
 
 +
\startreusableMPgraphic{Frame}
 +
  numeric u,v,xshift,yshift,picwidth,remnant,nelements;
  
<texcode>
+
  u := OverlayWidth;
\startreusableMPgraphic{name}
+
  v := OverlayHeight;
  fill fullcircle scaled 200pt withcolor .625yellow;
+
       
\stopreusableMPgraphic
+
  path p,w;
 +
  p := unitsquare xscaled u yscaled v;
 +
  w := fullcircle scaled 8pt;
 +
 +
  picture Edgepic,Linepic[];
 +
 
 +
  color edgedotcolor,linelementcolorA;
 +
 
 +
  edgedotcolor      := blue;
 +
  linelementcolorA := red;
  
\reuseMPgraphic{name}
+
  Linepic[1] := textext("\rotate[rotation=90]{= : =}");
</texcode>
+
  Linepic[2] :=  textext("= : =");
 +
  Edgepic    := textext("o");
 +
 +
  %Calculations for the horizontal frame-element placement:
 +
    % In order to make this work, the width of the line element needs to be calculated on beforehand.
 +
    % path PicX; PicX := textext(")(");
 +
  picwidth    := bbwidth(PicX);
 +
  nelements := u div picwidth;
 +
  remnant    := u mod picwidth;
 +
  xshift        := picwidth + remnant/nelements;
  
When reusing a graphic is not so important and you just want to include something inline, you can also use the following:
+
  Linepic[3] := Linepic[2] shifted (0.5*picwidth,0);
  
<texcode>
+
  for a = llcorner p, ulcorner p :
\startMPcode
+
      for i = 1 upto nelements :
   fill fullcircle scaled 200pt withcolor .625yellow;
+
        draw Linepic[3] shifted ((xpart a + (i-1)*xshift),ypart a) withcolor linelementcolorA;
\stopMPcode
+
      endfor;
</texcode>
+
  endfor;
 +
 +
  %Calculations for the vertical frame-element placement:
 +
  picheight   := bbwidth(PicX);
 +
  nelements := v div picheight;
 +
  remnant    := v mod picheight;
 +
  yshift        := picheight + remnant/nelements;
 +
 +
  Linepic[4]:= Linepic[1] shifted (0,0.5*picheight);
 +
 +
  for a = llcorner p, lrcorner p :
 +
      for i = 1 upto nelements:
 +
        draw Linepic[4] shifted (xpart a,ypart a + (i-1)*yshift) withcolor linelementcolorA;
 +
      endfor;
 +
  endfor;
  
See also section 3.3 of [[manual:metafun-s.pdf|MetaFun manual]].
+
  for i = llcorner p, lrcorner p,ulcorner p,urcorner p :
 +
      fill w shifted (xpart i,ypart i) withcolor white;
 +
        draw Edgepic shifted (xpart i,ypart i) withcolor edgedotcolor;
 +
  endfor;
  
=== Examples ===
+
% For frame-element positioning checking:
 +
%  draw p;
 +
%
 +
\stopreusableMPgraphic
  
{{todo|Enable support for Metapost code when running ConTeXt online. This will allow easy creation of Metapost examples, including both source code and resulted figure.}}
+
% ==========
  
Currently, running online Metapost code, like this example, does not return anything.
+
\startframedtext
 +
  [width=0.8\textwidth,height=0.8\textheight,frame=off,background=Myframe, align={middle,lohi}]
 +
      The butterfly counts not months but moments, and has time enough.
 +
      \blank
 +
      {\tfx Rabindranath Tagore}
 +
\stopframedtext
 +
\stoptext
  
<pre>
 
<context source="yes" text="produces">
 
\startMPcode
 
  fill fullcircle scaled 200pt withcolor .625yellow;
 
\stopMPcode
 
 
</context>
 
</context>
</pre>
 
  
== Other Links ==
+
 
 +
There is one important remark: The MPcalculation and the drawing itself must be inside \starttext ... \stoptext.
 +
 
 +
= Other Links =
  
 
* Metapost home page: http://tug.org/metapost
 
* Metapost home page: http://tug.org/metapost

Revision as of 07:52, 24 June 2020

MetaPost is a graphical programming language, based on Donald Knuth's MetaFont. Normally MP graphics are converted to PostScript and used with dvips, but ConTeXt can use it directly with PDF (see the MP to PDF manual).

MetaPost is ConTeXt's native graphics language. MetaFun - MetaPost in ConTeXt is a MetaPost module by Hans Hagen that adds a lot of extra features; it is enabled by default, so one could say that MetaFun is ConTeXt's default dialect of MetaPost.

Documentation & Tutorials

Using MetaPost in ConTeXt

With \startuseMPgraphic, you define a piece of graphics code that is processed anew every time the graphic is placed with \useMPgraphic. Further commands are described at MetaFun - MetaPost in ConTeXt.

\def\mycolor{.625red}

\startuseMPgraphic{name}
  fill fullcircle scaled 20pt withcolor \mycolor;
\stopuseMPgraphic

red: \useMPgraphic{name}

\def\mycolor{.625blue}
blue: \useMPgraphic{name}

Different Packages, Extensions & Applications of Metapost

  • finomaton - drawing finite state automata
  • statsmac - metapost macros for statistics graphs
  • MetaUML - MetaPost library for typesetting UML diagrams
  • METAGRAPH - drawing (un)directed graphs

3D support


TODO: needs major review (See: To-Do List)


MetaPost relatives

Font Creation

3D drawing

  • Asymptote - inspired by MetaPost & fully generalizes MetaPost path construction algorithms to three-dimensions

Testing plain MetaPost

To test whether MetaPost is installed on your system, create a file called test.mp:

beginfig(1)
  draw fullcircle scaled 3cm ;
endfig ;
end ;
  • apply MetaPost on the testfile
mp test.mp
or
mpost test.mp
  • that should create a postscript file test.1
  • open test.1 with a postscript viewer like Ghostview, Okular, … You should see a circle.

Testing MetaPost embedded in ConTeXt

If MetaPost is installed on your system and working correctly, you can

\starttext
\startMPcode
  draw fullcircle scaled 3cm;
\stopMPcode
\stoptext
  • for mkii you need to have write18 support enabled and run
texexec --pdf test.tex
  • for mkiv run
context test.tex
  • that should create a pdf file test.pdf
  • open test.pdf with a pdf viewer like Adobe Acrobat, Okular... You should see a circle.

Text in MetaPost

Text that is typeset using textext or btex … etex adapts to the body font. However, when label("Foo", pair) or "Foo" infont defaultfont is used, which is not the recommended way, the text is typeset using the font MetafunDefault, which can be changed if desired. Example:

\starttext
  \startMPcode
     label("Foo", origin);
     draw textext("Bar") yshifted -LineHeight;
  \stopMPcode

  \definefontsynonym
    [MetafunDefault]
    [Bold*default]

  \switchtobodyfont [pagella, 18pt]

  \startMPcode
     label("Foo", origin);
     draw textext("Foo") yshifted -LineHeight;
  \stopMPcode
\stoptext

Gives:

The recommended way to typeset text is to use the textext macro and change the font using \setupMPinstance.

Repetition of a Text Element to Fill a Bar Using textext

Imagine you want to create a frame which consists out of one glyph or a combination of different glyphs in order to make a decorative border. For this purpose a series of such elements should be placed on the bar as pictures, evenly spaced. Probably you want to have at the end of the bar a different glyph inserted as a picture too.

The following code is working but the last picture is not the expected glyph. One would expect 14 times the "?" and at the end of the bar a "*":

\starttext
   \startMPpage
      picture PicA ; PicA := textext("*");
      picture PicB ; PicB := textext("?");

      numeric Step ; Step := 2cm div bbwidth(PicB)  ;

      for i = 1 upto Step :
         draw PicB shifted (i*5mm,0) ;
      endfor ;
      draw PicA ;
   \stopMPpage
\stoptext

Gives:

What you get is 15 "?" but no "*"!

In order to get this corrected one needs to calculate the boundingbox of the "?" on beforehand. Hans Hagen provided this solution on 14-10-2014.

\starttext
   \startMPcalculation
       path PicX ; PicX := boundingbox textext("?") ;
   \stopMPcalculation

   \startMPpage
      picture PicA ; PicA := textext("*");
      picture PicB ; PicB := textext("?");

      numeric Step ; Step := 2cm div bbwidth(PicX) ;
      % numeric Step ; Step := 2cm div bbwidth(PicB)  ;

      for i = 1 upto Step :
         draw PicB shifted (i*5mm,0) ;
      endfor ;
      draw PicA ;
   \stopMPpage
\stoptext

Gives:

Now you get 14 "?" and the "*".

A Full Example

\setupbodyfont [8pt]

\defineoverlay[Myframe][\reuseMPgraphic{Frame}]

\setuppapersize[A8][A8]

\setuplayout
   [topspace=5mm,
    backspace=5mm,
    height=middle,
    width=middle,
    header=0pt,
    footer=0pt]

\starttext

% ======== Definition of the frame in Metafun ==========
\startMPcalculation
   path PicX ; PicX := boundingbox textext("= : =") ;
\stopMPcalculation	
   
\startreusableMPgraphic{Frame}
   numeric u,v,xshift,yshift,picwidth,remnant,nelements;

   u := OverlayWidth;
   v := OverlayHeight;
        
   path p,w;
   p := unitsquare xscaled u yscaled v;
   w := fullcircle scaled 8pt;
	
   picture Edgepic,Linepic[];
  
   color edgedotcolor,linelementcolorA;
  
   edgedotcolor       := blue;
   linelementcolorA := red;

   Linepic[1] := textext("\rotate[rotation=90]{= : =}");
   Linepic[2] :=  textext("= : =");
   Edgepic    := textext("o");
	
   %Calculations for the horizontal frame-element placement:
     % In order to make this work, the width of the line element needs to be calculated on beforehand.
     % path PicX; PicX := textext(")(");
   picwidth    := bbwidth(PicX);
   nelements := u div picwidth;
   remnant    := u mod picwidth;
   xshift        := picwidth + remnant/nelements;	 

   Linepic[3] := Linepic[2] shifted (0.5*picwidth,0);

   for a = llcorner p, ulcorner p :
      for i = 1 upto nelements :
         draw Linepic[3] shifted ((xpart a + (i-1)*xshift),ypart a) withcolor linelementcolorA;
      endfor;
   endfor;
	 			
   %Calculations for the vertical frame-element placement:
   picheight   := bbwidth(PicX);
   nelements := v div picheight;
   remnant    := v mod picheight;
   yshift        := picheight + remnant/nelements;
	 
   Linepic[4]:= Linepic[1] shifted (0,0.5*picheight);
	 
   for a = llcorner p, lrcorner p :
      for i = 1 upto nelements:
         draw Linepic[4] shifted (xpart a,ypart a + (i-1)*yshift) withcolor linelementcolorA;
      endfor;
   endfor;

   for i = llcorner p, lrcorner p,ulcorner p,urcorner p :
      fill w shifted (xpart i,ypart i) withcolor white;
        draw Edgepic shifted (xpart i,ypart i) withcolor edgedotcolor;
   endfor;

% For frame-element positioning checking:
%   draw p;
%
\stopreusableMPgraphic

% ==========

\startframedtext
   [width=0.8\textwidth,height=0.8\textheight,frame=off,background=Myframe, align={middle,lohi}]
      The butterfly counts not months but moments, and has time enough.
      \blank
      {\tfx Rabindranath Tagore}
\stopframedtext
\stoptext

Gives:


There is one important remark: The MPcalculation and the drawing itself must be inside \starttext ... \stoptext.

Other Links