…is code to define what the labels and cave symbols in pdf and svg outputs look like.

(Add another metapost links here)

pstoedit translates PostScript and PDF graphics into other vector formats, Metapost format too.
TUG's listing of MetaPost on the Web
MetaPost tutorial, Robert Špalek, česky
Many interesting MetaPost examples, gallery what is possible to do with MP
Page with many links to Metapost documentation and examples
Learning METAPOST by Doing, André Heck (pdf)
Loria: The Metafun manual, Hans Hagen, 2000 (pdf)
or: Pragma: The Metafun manual, Hans Hagen, 2000 (pdf)
Puzzling graphics in METAPOST, Hans Hagen (pdf)
Many nice examples
Many links from Michio Matsuyama, but you have to copy the text and open it as html file
Java based MetaPost Editor and Previewer (MEPer)

If you are brave Marco has written more than I ever wanted to know here Therion by Examples Metapost and here - Chapter 7

How to get Therions MetaPost code (and Tex code)

You can use this code as a starting point to make your own customisations.
You can either start with the unadulterated source code (perhaps the best way, and as described here) or you can use the code that has been updated with any modifications already present in your current setup (often useful as well if you want to see the end result of your definitions and re-definitions)- as described below.

You need to run Therion in debug mode (command line -d option) Here is how to run Therion in debug mode using the Xtherion Compilerto tell it to produce and retain a folder with interim outputs (not to be confused with layout-debug which can produce 2D outputs with station names, scrap names, intermediate scrap distortions etc).

The folder produced is called thTMPDIR

It contains;

  • data.mp = a dump of all the metapost code used by Therion
  • data.tex = a dump of all the tex code used by Therion

and perhaps less usefully…

  • th_texts.tex = ascii dump of all tex variables
  • th_legend.tex = similar dump of the legend
  • and much more…

Skim through data.mp and data.tex to find definitions and snippets of code that you'd like to edit.

Copy these to a code-tex or code-metapost block in a layout in one of your *.th or thconfig-*.* files, and make your edits.

The files produced in thTMPDIR will now reflect the code you have entered in your layouts.


By the way, you might be able to use the following to track down errors in metapost code (or in scrap drawings).

faq#how_to_find_where_a_metapost_error_is_occurring



Symbol Sizing

On Sun, Feb 7, 2010 Bruce wrote:

Is u: (and v: w: for that matter) intended to correspond to a
particular drawn entity size in the finished pdf, or are they just
arbitrary variables for which one can calculate the value of, using
the code in the initialise definition?
Bruce

u allows nonlinear scaling of symbols depending on scale. The macro initialize assigns a fixed value to 'u' which will be used in pdf for that scale. On average, diameter of point symbols is 1u in the output.

v and w behave differently (v could be used e.g. for some area fills with decreasing distance among symbols for smaller scales but only up to a certain threshold, then bigger distance again; w is almost constant). Currently they are not (or perhaps only occasionaly) used in symbols design.

In the beginning we wanted to do some sort of optimization of values assigned to u, v, w but did not manage to do it so far. It would be useful if somebody could test alternative values (and alternative breaks for map scale in the initialize macro) for various scales and various styles of map drawing (lot of symbols vs. sparsely filled map). Good setup of these values could improve map appearance substantially.

Cheers, Martin


For example; centrelines, water, point altitudes
View whole centerline for underground (Stacho Mudrak)

If you wish to view whole centerline for underground, just redefine symbol in layout:

    code mpost
      let l_survey_cave = l_survey_surface_SKBB;
    endcode

Visualize cave centreline shot flags with colour for splay and duplicate, and dash for approximate shot flags

For version 5.3.12+ Dec2013 (Bruce Mutton)

code metapost #thin grey cave splays, yellow duplicates and dashed approximate legs
  def l_survey_cave (expr P) =
  % always draws full centreline, rather than short stubs like default cave centrelines
	T:=identity;
	pickup PenC;
	if ATTR__shotflag_splay:
	  drawoptions(withcolor(0.5,0.5,0.5) withpen PenD);
	  thdraw P; %  grey & thin
        drawoptions();
	else: % not splay but may have either or both duplicate and approx flags set
		if ATTR__shotflag_duplicate: 
		  drawoptions(withcolor (1,1,0)); % differentiate duplicate with colour yellow
		fi;
	  
	    if ATTR__shotflag_approx:
		  thdraw P dashed evenly scaled optical_zoom;	% differentiate approx with dashed
		else:
		  thdraw P;
		fi;	
	    thdrawoptions();
    fi;
  enddef;
  endcode
  

I was trying to get the duplicate and approximate symbols to appear in the legend as below, but so far it does not work…

initsymbol("l_survey_cave_duplicate");  %not working
  
def l_survey_cave_duplicate_legend =
  l_survey_cave_duplicate(((.2,.2) -- (.8,.8)); inscale) %not working
enddef;  
  
 

—- How to show area water in a different color (Martin Budaj)

Add in layout:

  
  code metapost
    def a_water (expr p) =
      T:=identity;
      thfill p withcolor (0.1, 0.2, 0.8);
    enddef;
  endcode

Colors are in order R, G, B — 0=0 1=255. Color (0.1, 0.2, 0.8) means (25 51 204) in Photoshop - quite dark blue. Light blue could be for example (123 213 255) in Photoshop - it is (123/255, 213/255, 255/255) or (0.48, 0.84 1.0) for Metapost.

See also this spreadsheet to visualise and convert between colour formats.

Green colored continuous centerline from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

  def l_survey_cave (expr p) =
    pickup PenC;
    draw p withcolor 0.5green;
  enddef;

Code to make unsurveyed wall lines light-weight and dashed
A sample of how it looks is in the 'line rope' example below.

  code metapost
  %Bruce Mutton 2010.06.20 for Therion 5.3.9
  def l_wall_unsurveyed (expr P) = 
    T:=identity;
    pickup PenC;
    thdraw P dashed evenly scaled (2*optical_zoom);
  enddef;
  endcode

Code to define NZSS line wall presumed
Draws dashes with v shaped tick marks outside the passage like we tend to do in New Zealand…
A sample of how it looks is in the 'line rope' example below.

  code metapost
  %Bruce Mutton 2010.06.20 uses general code and adjust_step defined in therion source code by Martin Budaj
  %for Therion 5.3.8
  def l_wall_presumed (expr P) =
    T:=identity;
    cas := 0;                                 % cursor to step along path
    dlzka := arclength P;
    mojkrok:=adjust_step(dlzka, 1.5u);        % symbol length nudged to be multiple of path length
    q  := (-0.2u,-0.4u)--(0,0)--(0.2u,-0.4u); % define v shape 
    forever:
      t1 := arctime (cas + mojkrok*1/5) of P;
      t  := arctime (cas + mojkrok/2) of P;
      t2 := arctime (cas + mojkrok*4/5) of P;
        pickup PenA;                          % thick
  	thdraw (subpath (t1,t2) of P);          % dash
  	  pickup PenC;                          % thin
      thdraw q rotated angle(thdir(P,t)) shifted (point t of P ); % v shape

      cas := cas + mojkrok;
      exitif cas > dlzka - (2*mojkrok/3);     % for rounding errors
    endfor;
  enddef;
  endcode 

Code to define NZSS line chimney (aven)

  code metapost
  %Bruce Mutton 2012.06.10 uses general code for l_pit_UIS defined in therion source code by Martin Budaj 5.3.9
  % dots on righthand (rock) side of line spaced 0.2u, 0.2u same as floor-step ticks
  def l_chimney (expr P) = 
    T:=identity;
    cas := 0;                            % cursor to step along path
    dlzka := arclength P;
    mojkrok:=adjust_step(dlzka, 0.25u);  % symbol length nudged to be multiple of path length
    q:= (0.20u,-0.20u) -- (0.21u,-0.21u);         % dot
   
    pickup PenC;  %2nd thinnest pen
    forever:
      t := arctime cas of P;
  	thdraw q rotated angle(thdir(P,t)) shifted (point t of P ); % draw dots
  	cas := cas + mojkrok;
      exitif cas > dlzka + (mojkrok / 3); % for rounding errors
    endfor;
    pickup PenB;   %2nd thickest pen
    thdraw P;      %continuous line
  enddef;
  endcode
  

Code to define NZSS line ceiling-step
This is just Therions default SKBB ceiling step, reflected so that it matches the UIS convention with the tick marks pointing away from the void space.

code metapost
%Bruce Mutton 2012.06.16 uses general code for l_ceilingstep_SKBB defined in therion source code by Martin Budaj 5.3.9
% but ticks on righthand (rock) side of line 
def l_ceilingstep (expr P) =
  T:=identity;
  cas := 0;                            % cursor to step along path
  dlzka := arclength P;
  mojkrok:=adjust_step(dlzka, 0.8u);   % symbol length nudged to be multiple of path length
  pickup PenC;
  forever:
    t1 := arctime (cas + mojkrok*1/5) of P;
    t  := arctime (cas + mojkrok/2) of P;
    t2 := arctime (cas + mojkrok*4/5) of P;
    thdraw (subpath (t1,t2) of P);
    mark_ (P,t,-0.2u);                  % change sign to -0.2u
    cas := cas + mojkrok;
    exitif cas > dlzka - (2*mojkrok/3); % for rounding errors
  endfor;
enddef;
endcode

Code to define NZSS line ceiling-meander
This is just Therions default SKBB ceiling meander, with the symbols reflected so that it matches the UIS convention with the tick marks pointing away from the void space.

code metapost
%Bruce Mutton 2012.06.16 uses general code for l_ceilingmeander_SKBB defined in therion source code by Martin Budaj 5.3.9
% but ticks on outside (rock) side of lines 
def l_ceilingmeander (expr P) =
  pair Pp;
  pair Pd;
  pair Pv;
  T:=identity;
  cas := 0;                           % cursor to step along path
  dlzka := arclength P;
  mojkrok:=adjust_step(dlzka, 0.8u);  % symbol length nudged to be multiple of path length
  pickup PenC;
  forever:
    t  := arctime (cas + mojkrok/2) of P;
    Pp := (point t of P);
    Pd := unitvector(thdir(P,t));
    Pv := Pd rotated 90;
    thdraw (Pp + 0.2u * Pv) --
          (Pp + 0.3u * Pv);              % add 0.1u to each moves ticks outside
    thdraw (Pp + 0.2u * Pv + 0.2u * Pd) --
          (Pp + 0.2u * Pv - 0.2u * Pd);  
    thdraw (Pp - 0.2u * Pv) --
          (Pp - 0.3u * Pv);              % subtract 0.1u to each moves ticks outside
    thdraw (Pp - 0.2u * Pv + 0.2u * Pd) --
          (Pp - 0.2u * Pv - 0.2u * Pd); 
    cas := cas + mojkrok;
    exitif cas > dlzka - (2*mojkrok/3);  % for rounding errors
  endfor;
enddef;
endcode
  

Code to define a user point symbol for a stalagmite boss (Dave Clucas 2014)

def p_u_boss (expr pos,theta,sc,al)=
  T:=identity aligned al rotated theta scaled sc shifted pos;
  pickup PenD;
  p := (0.08u,0.25u)..(0,0.29u)..(-0.08u,0.25u);
  q := (0.16u,0.5u)..(0u,0.58u)..(-0.16u,0.5u);
  for i=0 upto 9:
   thdraw p rotated 36i;
   thdraw q rotated 36i;
  endfor
  p := fullcircle scaled 0.15u; 
  thdraw p;
enddef;

Code to define an entrance symbol as a theta inside a diamond (Dave Clucas 2014)

def p_entrance_MY (expr pos,theta,sc,al)=
  U:=(.2u,.5u);
  T:=identity aligned al rotated theta scaled sc shifted pos;
  path p;
  p = (-.3u,-.25u) -- (-.2u,-.25u){dir 135} .. (0u, .25u) .. {dir 225}(.2u,-.25u) -- (.3u,-.25u);
  thdraw p withpen PenA;
  thdraw unitsquare scaled u shifted (-0.5u,-0.5u) rotated 45 withpen PenD;
enddef;

Code to define a user point symbol for a single large irregular block (Dave Clucas 2012)

def p_u_block(expr pos,theta,sc,al) =
  T:=identity aligned al rotated theta scaled sc shifted pos;
  path p q;
  p := (2.3u,0.9u)--(0.65u,1u)--(-0.9u,0.6u)--(-2.15u,-0.1u)--(-2.35u,-0.25u)--(-2.5u,-0.5u)--(-2u,-0.65u)--(-0.75u,-0.65u)--(0.6u,-0.7u)--(1.1u,-0.5u)--(2.1u,-0.15u)--cycle;
  pickup PenB;
  thdraw p;
  % The following line uses the code from Colour Dependant Visualization of Symbols by Bruce Mutton
  if known colour_block_bg: thfill p withcolor colour_block_bg; else: thfill p withcolor (0.75,0.75,0.75); fi;
  q := (-2.5u,-0.5u)--(-2u,-0.65u)--(-0.75u,-0.65u)--(0.6u,-0.7u)--(1.1u,-0.5u)--(2.1u,-0.15u)--(2.3u,0.9u)--(2.5u,0.7u)--(2.5u,0.5u)--(2.25u,-0.9u)--(1.1u,-1.3u)--(0.5u,-1.5u)--(-0.75u,-1.4u)--(-2u,-1.15u)--(-2.35u,-0.65u)--cycle;
  thdraw q;
  thfill q withcolor(0.6,0.6,0.6);
  pickup PenD;
  path p;
  p := (-2u,-0.65u)--(-1.9u,-1u);
  thdraw p;
  path p;
  p := (0.6u,-0.7u)--(0.5u,-1.3u);
  thdraw p;
  path p;
  p := (2.1u,-0.15u)--(2.3u,-0.4u);
  thdraw p;
enddef;
initsymbol("p_u_block");

code to draw a plank walk and (rope) handrail (Dave Clucas 2014)

  def l_u_plankwalk  (expr P) = T:=identity;
    cas := 0;
    dlzka := arclength P;
    mojrok := adjust_step(dlzka, 0.5u);
    pickup PenD;
    forever:
      t := arctime cas of P;
      thdraw ((point t of P) + 0.5 * u * unitvector(thdir(P,t) rotated 90)) --
      ((point t of P) - 0.5 * u * unitvector(thdir(P,t) rotated 90) );
      cas := cas + mojrok;
      exitif cas > dlzka + (mojrok/3);  % for rounding errors
    endfor;
    pickup PenC;
    %thdraw P; 
    %draw path withcolor (0.5, 0 ,0)
   enddef;
   def l_u_handrail (expr P) = T:=identity;
    pair zz[];
    for t = 0 upto length P - 1:
      zz1 := point t of P;
      zz2 := point t+1 of P;
      zz3 := 0.5[zz1,zz2];
      zz4 := 0.25[zz1,zz2];
      zz5 := 0.75[zz1,zz2];
      pickup PenA;
      thdraw zz1 -- zz2 withcolor(.67,.41,.28); %planks
      thdraw zz1 shifted (0,1.6u) .. zz4 shifted (0,1.2u) .. zz3 shifted (0,1.6u) .. zz5 shifted (0,1.3u) .. zz2 shifted (0,1.6u) withcolor(.67,.41,.28);
      pickup pencircle scaled 1pt;
      thdraw zz1 shifted (0,-1.2u) -- zz1 shifted (0,2u) withcolor(.67,.41,.28); %first post
      thdraw zz3 -- zz3 shifted (0,2u) withcolor(.67,.41,.28); %mid post
    endfor;
    thdraw zz2 shifted (0,-6u) -- zz2 shifted (0,2u) withcolor(.67,.41,.30); %last post
   enddef;

code to define a doline (Dave Clucas 2014)

  def l_u_doline (expr P) =
    T:=identity;
    laenge:= arclength P;
    symsize:=adjust_step(laenge,2u);
    triangle_width:=symsize/10;
    cur:=(symsize-triangle_width)/2;
    pickup PenC;
    forever:
      t1 := arctime (cur) of P;
      t  := arctime (cur + triangle_width/2) of P;
      t2 := arctime (cur + triangle_width) of P;
        thfill (subpath (t1,t2) of P) -- 
          ((point t of P) + symsize/2 * unitvector(thdir(P,t) rotated 90)) -- 
          cycle;
        thdraw (point t2 of P) --((point t of P) + symsize/2 * unitvector(thdir(P,t) rotated 90)) -- 
          (point t1 of P) withcolor (0.5, 0, 0);
      cur := cur + symsize;
      exitif cur > laenge - (1*symsize/3); % for rounding errors
      t1:=arctime (cur) of P;
    endfor;
  enddef;


Modification MetaPost code for NSS (Philip Schuchardt)

This is how you overload metapost symbols:

######### thconfig file ###########

  input layout.th
  source main.th
  
  #One page map
  export map -layout plan -output ABC.pdf
  export map -layout print -output ABC_Printable.pdf

########## Heres my layout.th ################

  layout plan
    scale 1 200 #Working map scale
    #scale 1 400
    #scale 1 600 #1" to 50'
    #base-scale 1 600
    units imperial
    legend on
    color map-fg altitude
    transparency on
    debug station-names
  
    #PDF DOCUMENTION
    doc-author "Philip Schuchardt"
    code tex-map
      \cavename={Alva Blankenship Cave (WORKING COPY }
      \comment{Cartography By: Philip Schuchardt and Philip Balister  \copyright 2006 VPI Cave Club}
    endcode
  
  code metapost
      def l_wall_bedrock_AMER (expr P) =
        T:=identity;
        pickup PenA;
        thdraw P;
      enddef;  
  
      def p_gradient_AMER (expr pos,theta,sc,al) =
          U:=(.15u, .4u);
          T:=identity aligned al rotated theta scaled sc shifted pos;
          pickup PenC;
  
          #Left Hand side
          thdraw (-.3u, -.2u) -- (-.7u, .1u);
          thdraw (-.2u, -.1u) -- (-.4u, .6u);
  
          #Centerline
          thdraw (0u, 0u) -- (0u, .9u);
  
          #Right side
          thdraw (.3u, -.2u) -- (.7u, .1u);
          thdraw (.2u, -.1u) -- (.4u, .6u);
  
      enddef;
  
      def a_sand_AMER (expr p) =
        T:=identity;
        %  thclean p;
        pickup PenC;
        path q; q = bbox p;
        picture tmp_pic; 
        tmp_pic := image(
          for i = xpart llcorner q step .3u until xpart urcorner q:
            for j = ypart llcorner q step .3u until ypart urcorner q:
              draw origin shifted ((i,j) randomized 0.2u) withpen PenC;
            endfor;  
          endfor;
        );
        clip tmp_pic to p;
        draw tmp_pic;
      enddef;
  
      def a_debris_AMER (expr p) =
      T:=identity;
      pickup PenC;
      path q, qq; q = bbox p;
      picture tmp_pic; 
      tmp_pic := image(
        for i = xpart llcorner q step u until xpart urcorner q:
         for j = ypart llcorner q step u until ypart urcorner q:
            qq := punked 
  (((-.2u,-.2u)--(.2u,-.2u)--(.2u,.2u)--(-.2u,.2u)--cycle) 
  	     randomized (u/2))
               rotated uniformdeviate(360) 
               shifted ((i,j) randomized u);
  	   if xpart (p intersectiontimes qq) < 0:
  	    thclean qq;
  	    thdraw qq;
  	   fi;
          endfor;  
        endfor;
      );
      clip tmp_pic to p;
      draw tmp_pic;
    enddef;
  
    initsymbol ("a_sand_AMER");
    initsymbol ("a_debris_AMER");
    initsymbol ("p_gradient_AMER");
    initsymbol ("l_wall_bedrock_AMER");
    endcode
  
    symbol-assign area sand AMER
    symbol-assign area debris AMER
    symbol-assign line wall:bedrock AMER
    symbol-assign point gradient AMER
  
  endlayout

Modification of fill densities (Stacho Mudrák)

   code metapost
   % pattern for water, .18u is density of lines.
   beginpattern(pattern_water_MY);
       draw origin--10up withpen pensquare scaled (0.02u);
       patternxstep(.18u);
       patterntransform(identity rotated 45);
   endpattern;
  
  % pattern for sump, 0.25u is density in this case.
  beginpattern(pattern_sump_MY);
       draw origin--(0,.25u) withpen pensquare scaled (0.02u);
       draw origin--(.25u,0) withpen pensquare scaled (0.02u);
       patterntransform(identity rotated 45);
  endpattern;
  
  def a_water (expr Path) =
     T:=identity;
     thclean Path;
     thfill Path withpattern pattern_water_MY;
  enddef;
  
  def a_sump (expr Path) =
     T:=identity;
     thclean Path;
     thfill Path withpattern pattern_sump_MY;
  enddef;
  
  endcode

… and modify 0.18u in water pattern (and/or 0.25u in sump pattern) to number you need.

In therion, area symbols are defined two ways:

  1. Using patterns - no randomness, very small PDF file size. You need to redefine pattern (begin|endpattern) and symbol macro (a_water).
  2. Using drawing/clipping into Path - random look, large PDF size. Here you need to redefine only symbol (a_water) macro.

Water is the case of pattern fills. Blocks and others are random.

For other area symbols, see mpost/thArea.mp file for metapost source codes.


POINT BLOCK +size adjust (symbolsize) Stefan Oswald

  code metapost
   def p_blocks_UIS (expr pos,theta,sc,al)=
    symbolsize:=1.0u; %Factor*u; Factor=size of the blocks
    U:=(.5u,.5u);
    T:=identity aligned al rotated theta scaled sc shifted pos;
    pickup PenC;
    thdraw (.0symbolsize,.0symbolsize)--(1.0symbolsize,-.5symbolsize)--(0.0symbolsize,-1.5symbolsize)--(-1.0symbolsize,-1.0symbolsize)--cycle;
    thdraw (.5symbolsize,-.25symbolsize)--(1.0symbolsize,.5symbolsize)--(0.0symbolsize,1.5symbolsize)--(-0.5symbolsize,.5symbolsize);
    thdraw (.0symbolsize,.0symbolsize)--(.0symbolsize,.5symbolsize)--(-1.5symbolsize,.5symbolsize)--(-1.5symbolsize,-0.5symbolsize)--(-0.5symbolsize,-0.5symbolsize);
   enddef;
  endcode

AREA BLOCK + density adjust (distance) Stefan Oswald

  code metapost
    def a_blocks (expr p) =
      distance:=1;
      T:=identity;
      pickup PenC;
      path q, qq; q = bbox p;
      picture tmp_pic; 
      uu := max(u, (xpart urcorner q - xpart llcorner q)/100, (ypart urcorner q - ypart     llcorner q)/100);
      tmp_pic := image(
        for i = xpart llcorner q step distance*uu until xpart urcorner q:
          for j = ypart llcorner q step distance*uu until ypart urcorner q:
            qq := punked (((-.5uu,-.5uu)--(.5uu,-.5uu)--(.5uu,.5uu)--(-.5uu,.5uu)--cycle) 
          randomized (uu/2))
                 rotated uniformdeviate(360) 
                 shifted ((i,j) randomized 1.0uu);
      if xpart (p intersectiontimes qq) < 0:
        thclean qq;
        thdraw qq;
      fi;
          endfor;  
        endfor;
      );
      clip tmp_pic to p;
      draw tmp_pic;
    enddef;  
  endcode

Code to make area AUT sand more spaced out and more random
A sample of how it looks is in the 'area point colour water' example below.

  code metapost
  %Bruce Mutton 2010.06.20, after original author Georg Pacher
  %for Therion 5.3.8
  beginpattern(pattern_sand);
      pickup PenC;
      p:= origin -- (0.01u,0.01u);
      for i=0.0u step 0.4u until 2.4u:  %AUT is step 0.2u 
          for j=0.0u step 0.4u until 2.4u:  %AUT is step 0.2u 
            draw p rotated uniformdeviate(360) 
             shifted ((i,j) randomized 0.4u);  %%AUT is 0.09u
          endfor;
      endfor;
      if BaseScale<=2.5:
        my_step:=2.6u;  %mystep controls tessilation pattern, must synchronise with i, j above, was 2.4u
      else:
        my_step:=2.8u;  %was 2.6u
      fi;
      patternstep(my_step,my_step);       
  endpattern;
  def a_sand (expr Path) =
    T:=identity;
    %thclean Path; %makes passage colour more intense under area, not good for sand
    thfill Path withpattern pattern_sand ;
  enddef;
  endcode


To make the debug station names smaller (Stacho Mudrak)

Currently, there is no easy way to do this, but it is possible. You just need to redefine fonts_setup metapost macro using layout. Just add following code to your layout:

code metapost def fonts_setup (expr t,s,m,l,h) =

write "\def\updown#1#2{\vbox{" &
      "\offinterlineskip" &
      "\setbox100=\hbox{#1}" &
      "\setbox101=\hbox{#2}" &
      "\ifnum\wd100>\wd101\hsize=\wd100\else\hsize=\wd101\fi" &
      "\centerline{\box100}\vskip4pt" &
      "\centerline{\box101}}}" &
      "\def\thlabel{\thnormalsize}" &
      "\def\thremark{\thsmallsize\si}" &
      "\def\thaltitude{\thsmallsize}" &
      "\def\thstationname{\thsmallsize}" &
      "\def\thdate{\thsmallsize}" &
      "\def\thheight{\thsmallsize}" &
      "\def\thheightpos{\thsmallsize+\ignorespaces}" &
      "\def\thheightneg{\thsmallsize-\ignorespaces}" &
      "\def\thframed{\thsmallsize}" &
      "\def\thwallaltitude{\thtinysize}"
to "mptexpre.tex";
write "\def\thtinysize{\size[" & decimal max(optical_zoom*t,0) & "]}" &
      "\def\thsmallsize{\size[" & decimal max(optical_zoom*s,0) & "]}" &
      "\def\thnormalsize{\size[" & decimal max(optical_zoom*m,0) & "]}" &
      "\def\thlargesize{\size[" & decimal max(optical_zoom*l,0) & "]}" &
      "\def\thhugesize{\size[" & decimal max(optical_zoom*h,0) & "]}"
to "mptexpre.tex";
write "\def\thstationname{\size[4]}" to "mptexpre.tex";
write EOF to "mptexpre.tex";

enddef; initialize(Scale); endcode

It may look crazy at first sight, but it is not so bad. I have just added this line to the standard code:

write "\def\thstationname{\size[4]}" to "mptexpre.tex";

… and this line tells metapost to use font size 4 for station names.

I want my north arrow to have a label, like “Norte Geografico” (Carlos Grohmann & Martin Budaj)

  def s_northarrow_SKBB (expr rot) =
    T:=identity scaled 0.7 rotated -rot;
        begingroup
        interim defaultscale:=1;
        label(btex Norte Geografico etex, (0,-1cm));
      endgroup;
    thdraw (-.5cm,-1cm)--(0,1.5cm)--(.5cm,-1cm)--(0,-.5cm)--cycle;
    thfill (-.5cm,-1cm)--(0,1.5cm)--(0,-.5cm)--cycle;
  enddef;

Altitude Point
from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

This label requires to specify the position of text relative to point with help of -altitude. In this case -altitude bottom-right

  def p_altitude(expr pos)=
    T:=identity shifted pos;
    pickup PenD;
    p:=(-.3u,0)--(.3u,0);
    thdraw p; thdraw p rotated 90;
    p:=fullcircle scaled .2u;
    thclean p; thdraw p;
  enddef;
  
  vardef p_label@#(expr txt,pos,rot,mode) =
    if mode=1:
      thdrawoptions(withcolor .8red + .4blue);
      p_altitude(pos);
      % append "m" to label
      picture txtm;
      txtm:=image(
        draw txt;
        interim labeloffset:=0;
        label.urt(btex \thaltitude m etex, lrcorner txt);
      );
      % give extra offset in case of l/r/t/b alignment
      pair ctmp;
      ctmp:=center thelabel@#("x", (0,0));
      if (xpart ctmp * ypart ctmp)=0:
        interim labeloffset:=(.4u);
      else: % diagonal alignment
        interim labeloffset:=(.2u);
      fi;
      % draw label
      lab:=thelabel@#(txtm, pos);
      draw lab _thop_; % use color
      thdrawoptions();
      bboxmargin:=0.8bp;
      write_circ_bbox((bbox lab) smoothed 2);
    else:
      if mode=7: interim labeloffset:=(u/8) fi;
      lab:=thelabel@#(txt, pos);
      if mode>1: pickup PenD fi;
      if mode=2: process_uplabel;
      elseif mode=3: process_downlabel;
      elseif mode=4: process_updownlabel;
      elseif mode=5: process_circledlabel;
      elseif mode=6: process_boxedlabel;
      elseif mode=7: process_label(pos,rot);  % station name
      elseif mode=8: process_filledlabel(pos, rot);
      else: process_label(pos,rot); fi;
    fi;
  enddef;
  

To make 'point height' have P prefix for pits and C prefix for climbs (Martin Budaj)

You just need to add following to your layout:

  code mpost
    verbatimtex \def\thheightpos{C}\def\thheightneg{P} etex

and use “point 0 0 height -value [+10 m]” or “point 0 0 height -value [-85 m]” in your data to get C10 or P85.

Conditional Printing of Text Labels

Forum post describing some labelling issues and how to conditionally print labels

(Thomas' 'Scale Dependant Visualization' posts below show a tidier way of redefining the built in metapost, that will better inherit future changes to the default label metapost)



Examples of North arrows, scale-bars, gridlines etc

Northarrow 1
from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

  def s_northarrow (expr rot) =
    begingroup
      interim defaultscale:=0.5; % scale your north arrow here
      T:=identity scaled defaultscale rotated -rot;
      pickup pencircle scaled (0.08cm * defaultscale);
      thdraw (-.4cm,-1.4cm)--(0,2.8cm)--(.4cm,-1.4cm)--cycle;
      p:=fullcircle scaled 1.6cm;
      thclean p; thdraw p;
      p:=(0.95cm,0)--(0.65cm,0);
      thdraw p; thdraw p xscaled -1;
      pickup pencircle scaled (0.12cm * defaultscale);
      p:=(0.28cm,0.42cm);
      thdraw p--(p yscaled -1)--(p xscaled -1)--(p scaled -1);
    endgroup;
  enddef;

Northarrow 2
from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

  def s_northarrow (expr rot) =
    begingroup
      interim defaultscale:=0.7; % scale your north arrow here
      T:=identity scaled defaultscale rotated -rot;
      interim linecap:=squared;
        interim linejoin:=rounded;
      thfill (-.5cm,-.1cm)--(0,2.5cm)--(.5cm,-.1cm)--cycle;
      pickup pencircle scaled (0.08cm * defaultscale);
      thdraw (0,0)--(0,-2.5cm);
      pickup pencircle scaled (0.16cm * defaultscale);
      p:=(0.4cm,0.6cm);
      thdraw ((p--(p yscaled -1)--(p xscaled -1)--(p scaled -1)) shifted (0,-1.0cm));
      label.rt(thTEX("mg") scaled 1.6, (.6cm,-1.6cm)) transformed T;
    endgroup;
  enddef;
  

Northarrow 3
from Stacho Mudrák for version 5.3.x…

distributed under the GNU General Public License.

  def s_northarrow_3 (expr rot) =
    T:=identity;
    picture tmp_pic;
    tmp_pic = image (
      begingroup
        interim defaultscale:=3;
        label.top("N", origin shifted (0,2.2cm));
      endgroup;
      thdraw (-.4cm,.4cm)--(0,2cm)--(.4cm,.4cm)--(2cm,0cm)--(.4cm,-.4cm)--(0,-2cm)--(-.4cm,-.4cm)--(-2cm,0)--cycle;
      thfill (-.4cm,.4cm)--(0,2cm)--(0,0)--cycle;
      thfill (.4cm,-.4cm)--(0,-2cm)--(0,0)--cycle;
      thfill (.4cm,.4cm)--(2cm,0)--(0,0)--cycle;
      thfill (-.4cm,-.4cm)--(-2cm,0)--(0,0)--cycle;
    );
    draw tmp_pic scaled 0.5 rotatedaround(origin, -rot);
  enddef;

Northarrow 4
:metapost:s_northarrow-Nmag.png?150|]]

from Dirk Peinelt for 5.3.16…

I combine this compass rose with a creation date in the map-header (/currentdate), as a date variable is not present in metapost.

Martin Sluka: There is simple way to add actual date into Metapost code. I add modified variation after original code.

If the CS is not set, the declination is Zero, and so based on the declination, the northarrow is a Nmag arrow:

North grid/true rotate the whole plan with the north arrow. (meridianal Convergence)

def s_northarrow (expr rot) =
            valscal=1.2; % scale your north arrow here
            decl:=MagDecl; 
            T:=identity;
            picture tmp_pic;
            tmp_pic = image (
                          pickup pencircle scaled .3;
                          thfill fullcircle scaled 4cm withcolor 1white;
                          thdraw fullcircle scaled 3.1cm;
                          thdraw fullcircle scaled 4.05cm;
                          pickup pencircle scaled .1;
                          thdraw fullcircle scaled 3cm;
                          thdraw fullcircle scaled 4cm;
                          pickup pencircle scaled .2;
                          thdraw (dir(45)*2.025cm)--(dir(45)*3.7cm);
                          thdraw (dir(135)*2.025cm)--(dir(135)*3.7cm);
                          thdraw (dir(225)*2.025cm)--(dir(225)*3.7cm);
                          thdraw (dir(315)*2.025cm)--(dir(315)*3.7cm);
                          pickup pencircle scaled .1;
                          for whereto=0 step 15 until 345:
                            thdraw dir(whereto)*.65cm--dir(whereto)*.9cm;
                            thdraw dir(whereto)*1.4cm--dir(whereto)*1.5cm;
                          endfor;
                          for whereto=0 step 5 until 355:
                            thdraw dir(whereto)*.65cm--dir(whereto)*.8cm;
                            thdraw dir(whereto)*1.45cm--dir(whereto)*1.5cm;
                          endfor; 
                          for whereto=0 step 1 until 359:
                            thdraw dir(whereto)*1.94cm--dir(whereto)*2cm;
                          endfor; 
                          pickup pencircle scaled 1;
                          thdraw fullcircle scaled 1cm;
                          thdraw fullcircle scaled 1.1cm;
                          thdraw fullcircle scaled 1.3cm withpen pencircle scaled .3;
                          vald=90-decl;
                          texrot=0-decl;
                          drawarrow(dir(vald)*-2cm--dir(vald)*2cm) withpen pencircle scaled .2;
                          if (MagDecl <> 0): thdraw image(label.top(btex $mg$ etex, (0,0)) scaled .5 rotated texrot;) shifted (dir(vald)*2.04cm); fi;                                               
                          thfill (1.06cm,1.06cm)--(0,.2cm)--(-1.06cm,1.06cm)--(-.2cm,0)--(-1.06cm,-1.06cm)--(0,-.2cm)--(1.06cm,-1.06cm)--(.2cm,0)--cycle;
                          thfill (-.2cm,.2cm)--(0,2cm)--(0,0)--cycle;
                          thfill (.2cm,-.2cm)--(0,-2cm)--(0,0)--cycle;
                          thfill (.2cm,.2cm)--(2cm,0)--(0,0)--cycle;
                          thfill (-.2cm,-.2cm)--(-2cm,0)--(0,0)--cycle;
                          thfill (.2cm,.2cm)--(-0,2cm)--(0,0)--cycle withcolor 1white;
                          thfill (.2cm,-.2cm)--(2cm,0)--(0,0)--cycle withcolor 1white;
                          thfill (-.2cm,-.2cm)--(0,-2cm)--(0,0)--cycle withcolor 1white;
                          thfill (-.2cm,.2cm)--(-2cm,0)--(0,0)--cycle withcolor 1white;                                     
                          pickup pencircle scaled .2;
                          thdraw (-.2cm,.2cm)--(0,2cm)--(.2cm,.2cm)--(2cm,0cm)--(.2cm,-.2cm)--(0,-2cm)--(-.2cm,-.2cm)--(-2cm,0)--cycle;
                          thfill fullcircle scaled .56cm withcolor 1white;
                          pickup pencircle scaled .1;
                          thdraw (.28cm,0)..(0,.28cm)..(-.28cm,0)..(0,-.28cm)..cycle;
                          pickup pencircle scaled .4;
                          thdraw (.2cm,0)..(0,.2cm)..(-.2cm,0)..(0,-.2cm)..cycle;
                          if (MagDecl = 0): label.bot(btex $Nmag$ etex, (0,2.6cm)); else: label.bot(btex $N$ etex, (0,2.6cm)); fi;
                          label.lft(btex $E$ etex, (2.6cm,0));
                          label.rt(btex $W$ etex, (-2.6cm,0));
                          label.top(btex $S$ etex, (0,-2.6cm));
            );
            thdraw tmp_pic scaled valscal rotatedaround(origin, -rot);
enddef;

Northarrow 4a

With actual date
If you want to use another font, check, please, one which include character “space”.

def s_northarrow (expr rot) =
            valscal=1.2; % scale your north arrow here
            decl:=MagDecl; 
            T:=identity;
            picture tmp_pic;
            tmp_pic = image (
                          pickup pencircle scaled .3;
                          thfill fullcircle scaled 4cm withcolor 1white;
                          thdraw fullcircle scaled 3.1cm;
                          thdraw fullcircle scaled 4.05cm;
                          pickup pencircle scaled .1;
                          thdraw fullcircle scaled 3cm;
                          thdraw fullcircle scaled 4cm;
                          pickup pencircle scaled .2;
                          thdraw (dir(45)*2.025cm)--(dir(45)*3.7cm);
                          thdraw (dir(135)*2.025cm)--(dir(135)*3.7cm);
                          thdraw (dir(225)*2.025cm)--(dir(225)*3.7cm);
                          thdraw (dir(315)*2.025cm)--(dir(315)*3.7cm);
                          pickup pencircle scaled .1;
                          for whereto=0 step 15 until 345:
                            thdraw dir(whereto)*.65cm--dir(whereto)*.9cm;
                            thdraw dir(whereto)*1.4cm--dir(whereto)*1.5cm;
                          endfor;
                          for whereto=0 step 5 until 355:
                            thdraw dir(whereto)*.65cm--dir(whereto)*.8cm;
                            thdraw dir(whereto)*1.45cm--dir(whereto)*1.5cm;
                          endfor; 
                          for whereto=0 step 1 until 359:
                            thdraw dir(whereto)*1.94cm--dir(whereto)*2cm;
                          endfor; 
                          pickup pencircle scaled 1;
                          thdraw fullcircle scaled 1cm;
                          thdraw fullcircle scaled 1.1cm;
                          thdraw fullcircle scaled 1.3cm withpen pencircle scaled .3;
                          vald=90-decl;
                          texrot=0-decl;
                          drawarrow(dir(vald)*-2cm--dir(vald)*2cm) withpen pencircle scaled .2;
                          if (MagDecl <> 0): 
                        	string z;
                        	z = ("mg " & (decimal day) & ". " & (decimal month) & ". " & (decimal year));
                        	thdraw image(label.urt( z infont "ptmr8r", (0,0)) scaled .5 rotated texrot;) shifted (dir(vald)*2.04cm);
                        	fi;                                                      
                          thfill (1.06cm,1.06cm)--(0,.2cm)--(-1.06cm,1.06cm)--(-.2cm,0)--(-1.06cm,-1.06cm)--(0,-.2cm)--(1.06cm,-1.06cm)--(.2cm,0)--cycle;
                          thfill (-.2cm,.2cm)--(0,2cm)--(0,0)--cycle;
                          thfill (.2cm,-.2cm)--(0,-2cm)--(0,0)--cycle;
                          thfill (.2cm,.2cm)--(2cm,0)--(0,0)--cycle;
                          thfill (-.2cm,-.2cm)--(-2cm,0)--(0,0)--cycle;
                          thfill (.2cm,.2cm)--(-0,2cm)--(0,0)--cycle withcolor 1white;
                          thfill (.2cm,-.2cm)--(2cm,0)--(0,0)--cycle withcolor 1white;
                          thfill (-.2cm,-.2cm)--(0,-2cm)--(0,0)--cycle withcolor 1white;
                          thfill (-.2cm,.2cm)--(-2cm,0)--(0,0)--cycle withcolor 1white;                                     
                          pickup pencircle scaled .2;
                          thdraw (-.2cm,.2cm)--(0,2cm)--(.2cm,.2cm)--(2cm,0cm)--(.2cm,-.2cm)--(0,-2cm)--(-.2cm,-.2cm)--(-2cm,0)--cycle;
                          thfill fullcircle scaled .56cm withcolor 1white;
                          pickup pencircle scaled .1;
                          thdraw (.28cm,0)..(0,.28cm)..(-.28cm,0)..(0,-.28cm)..cycle;
                          pickup pencircle scaled .4;
                          thdraw (.2cm,0)..(0,.2cm)..(-.2cm,0)..(0,-.2cm)..cycle;
                          if (MagDecl = 0): label.bot(btex $Nmag$ etex, (0,2.6cm)); else: label.bot(btex $N$ etex, (0,2.6cm)); fi;
                          label.lft(btex $E$ etex, (2.6cm,0));
                          label.rt(btex $W$ etex, (-2.6cm,0));
                          label.top(btex $S$ etex, (0,-2.6cm));
            );
            thdraw tmp_pic scaled valscal rotatedaround(origin, -rot);
enddef;

Scalebar 1
from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

  def s_scalebar (expr l, units, txt) =
    begingroup
      interim warningcheck:=0;
      tmpl:=l / Scale * cm * units / 2;
      tmpx:=l / Scale * cm * units / 5;
      tmph:=5bp; % bar height
    endgroup;
    pickup PenC;
    draw (-tmpl,0)--(tmpl,0)--(tmpl,-tmph)--(-tmpl,-tmph)--cycle;
    p:=(0,0)--(tmpx,0)--(tmpx,-tmph)--(0,-tmph)--cycle;
    for i:=-2.5 step 2 until 2:
      fill p shifted (i * tmpx,0);
    endfor;
    begingroup
      interim labeloffset:=3.5bp;
      for i:=0 step (l/5) until (l-1):
        tmpx:=tmpl * (i * 2 / l - 1);
        label.top(thTEX(decimal (i)),(tmpx,0));
      endfor;
      label.top(thTEX(decimal (l) & "\thinspace" & txt),(tmpl,0));
      label.bot(thTEX("Originalmassstab = 1 : " & decimal round(Scale*100)),(0,-tmph));
    endgroup;
  enddef;

Scalebar 2
from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

  def s_scalebar (expr l, units, txt) =
    begingroup
      interim warningcheck:=0;
      tmpl:=l / Scale * cm * units / 2;
      tmpx:=l / Scale * cm * units / 5;
      tmph:=5bp; % bar height
    endgroup;
    pickup PenC;
    draw (-tmpl,0)--(tmpl,0)--(tmpl,-tmph)--(-tmpl,-tmph)--cycle;
    p:=(0,0)--(tmpx,0)--(tmpx,-tmph)--(0,-tmph)--cycle;
    for i:=-2.5 step 2 until 2:
      fill p shifted (i * tmpx,0);
    endfor;
    begingroup
      interim labeloffset:=3.5bp;
      for i:=0 step (l/5) until (l-1):
        tmpx:=tmpl * (i * 2 / l - 1);
        label.bot(thTEX(decimal (i)),(tmpx,-tmph));
      endfor;
      label.bot(thTEX(decimal (l) & "\thinspace" & txt),(tmpl,-tmph));
      label.top(thTEX("Massstab 1 : " & decimal round(Scale*100)),(0,0));
    endgroup;
  enddef;

Scalebar Bar length adjustment
from Andrew Atkinson

Some of us have fussy editors, who point out that due to the drawing of the rectangle for the scale bar the black lines are not exactly the same size as the white ones.

To fix this for the two scale bars above

Replace

  draw (-tmpl,0)--(tmpl,0)--(tmpl,-tmph)--(-tmpl,-tmph)--cycle;
    

with

  #Adjusted to make lines not stick out: 0.25*u/10,0 is half thickness of PenC
  draw (-tmpl+0.25*u/10,0)--(tmpl-0.25*u/10,0);
  draw (tmpl-0.25*u/10,-tmph)--(-tmpl+0.25*u/10,-tmph);

Code to change grid symbols from cross hairs to continuous lines
from Stacho Mudrak (mostly) and Bruce Mutton 2007

  code metapost
  def s_hgrid (expr xpos, ypos, xsize, ysize) =
    pickup PenD;
    draw (
      if xpos < 0: 0 else: -xsize/2 fi, 0
    ) -- (
      if xpos > 0: 0 else: xsize/2 fi, 0
    ) withcolor 0.1black+0.5white;
    draw (
      0, if ypos < 0: 0 else: -ysize/2 fi
    ) -- (
      0, if ypos > 0: 0 else: ysize/2 fi
    ) withcolor 0.1black+0.5white;
  enddef;
  endcode


Examples of scale dependent labeling and symbol display etc

A lot of this does not require metapost code (ie much of it can be done with default therion layout syntax), so maybe put this topic on a page of it's own?

Hide small rocks

from Thomas Holder for version 5.2.x…

distributed under the GNU General Public License.

  def l_rockborder (expr p) =
    if abs(llcorner p - urcorner p) > u:
      l_rockborder_UIS(p);
    fi;
  enddef;
  
  def l_rockedge (expr p) =
    if abs(llcorner p - urcorner p) > u:
      l_rockedge_UIS(p);
    fi;
  enddef;


Examples of symbols that plot differently, dependant on whether particular colour variables are defined. Provides an easy way to toggle between producing maps optimised for black and white, and maps optimised for colour production.

Code to redefine area and point water symbols
Bruce Mutton 2010-2011 for Therion 5.3.8, 5.3.9

B&W area sump, water and point water of various scalesColour area sump, water and point water of various scales
The area water symbols have much more spaced hatch lines, more consistent with what we traditionally use in New Zealand. The black and white point and area water has no background shading whereas the colour versions do.

  #Patterns similar to standard definition of pattern_water_UIS and pattern_sump_UIS
  #Gives b&w shaded symbols with borders, unless custom colours are defined
  #in which case colour backgrounds defined in LayoutColourSymbols are used
  code metapost
  beginpattern(pattern_water);
      draw origin--10up withpen pensquare scaled (0.04u); % line thickness
      patternxstep(.50u);                                 % spacing
      patterntransform(identity rotated 45);
  endpattern;
  
  beginpattern(pattern_sump);
      draw origin--(0,.50u) withpen pensquare scaled (0.04u);
      draw origin--(.50u,0) withpen pensquare scaled (0.04u);
      patterntransform(identity rotated 45);	
  endpattern;
  
  
  def p_water (expr pos,theta,sc,al)=
  %Bruce Mutton 2010.06.20 for Therion 5.3.8
      U:=(.425u,.3u);
      T:=identity aligned al rotated theta scaled sc shifted pos;
      pickup PenD;
      p:=fullcircle xscaled (1.2u) yscaled (0.8u) randomized (0.1u) rotated uniformdeviate (-45);
      if known colour_water_bg: thfill p withcolor colour_water_bg; else: thfill p withcolor white; fi; 
      thfill p withpattern pattern_water; %%% withcolor black;  %but with failed attempt at black hatch
      thdraw p;   %outline
      enddef; 
  
  def a_water (expr Path) =
  %Bruce Mutton 2010.06.20 for Therion 5.3.8
    T:=identity;
    thclean Path;
    pickup PenD;
    if known colour_water_bg: thfill Path withcolor colour_water_bg; else: thfill Path withcolor white; fi; 
    thfill Path withpattern pattern_water;  
    %%thdraw Path;  %outline, not needed as area drawn is defined by line border anyway
     %and border can be made invisible with subtype invisible where water meets sump in elevation
  enddef;
  
  def a_sump (expr Path) =
  %Bruce Mutton 2010.06.20 for Therion 5.3.8
    T:=identity;
    thclean Path;
    pickup PenD;
    if known colour_sump_bg:  thfill Path withcolor colour_sump_bg; else: thfill Path withcolor 0.7white; fi;
    thfill Path withpattern pattern_sump;  
    %%thdraw Path;  %outline, not needed as area drawn is defined by line border anyway
     %and border can be made invisible with subtype invisible where water meets sump in elevation
  enddef;
  endcode

Code to define custom line rope symbol
Rope symbol in black and white and in colour

  code metapost
  #submitted by Christian Jackson Nov2011
  #modified for colour or black and white Bruce Mutton Nov2011
  def l_u_rope (expr P) =
  	T:=identity;
  	pickup pensquare scaled (1.0*u/10);
  	if known colour_rope: thdraw P withcolor colour_rope; else: thdraw P withcolor 0.1black+0.5white;
  	fi;
  	pickup PenC;
  	thdraw P dashed dashpattern(on 1bp off 2bp on 1bp off 2bp);
  enddef;
  
  initsymbol("l_u_rope")
  
  def l_u_rope_legend =
  	l_u_rope(((.2,.2) -- (.8,.8)) inscale)
  enddef;
  endcode

Need to add next line to all thconfig files to define legend text for the new custom rope symbol

  text en "line u:rope" "rope" #text to appear in legend

Code to make full colour symbols
Here is a layout where you can define the colours you would like to use with the above code when you don't want a black and white map. (The groups of the statements in the 'code metapost' block are the ones that work with the code above).
I have not included any opacity statements in here, but perhaps it would be a good idea. The degree of opacity that works well for black and white outputs seems to be quite different to that which works for colour outputs.

  
  layout LayoutColourSymbols
  #Still experimental (Dec 2011) and as per the comments in the code below, many of the default 
  #'symbol-colour' statements do not work as I would like.  The custom metapost 
  #components work fine however.
  
  #affects colour symbol linework but not labels and not fills
  	
  	symbol-colour point station [54 7 60]	#purple[54 7 60] #seems to affect +s, flag symbols and station text
  	
  	#survey cave
  	symbol-colour group cave-centreline [35 16 16] # brown [35 16 16] # red brown [50 0 0]
  	symbol-colour point cave-station [35 16 16]  #ineffective?
  	#symbol-colour point station-name [0 100 0]	
  	
  	#survey surface
  	symbol-colour group surface-centreline [54 74 29] # green [54 74 29]
  	symbol-colour point surface-station [54 74 29]  #ineffective?
  	symbol-colour point flag:entrance [54 74 29]  #ineffective?
  	
  	#magenta
  	symbol-colour group equipment  [80 0 40] # magenta [80 0 40]
  	
  	#dark blue
  	# symbol-colour group water  [22 22 95] # this breaks custom water definitions
  	symbol-colour point water-flow  [22 22 95]
  	symbol-colour line water-flow  [22 22 95]	
  	symbol-colour point water [22 22 95]	    # inconsistent?
  	# symbol-colour area sump [22 22 95]	# this breaks custom water definitions
  
  	#light blue	
  	# symbol-colour area water [86 100 100]	# this breaks custom water definitions
  	
  	#define colours for redefined water point & area
  	code metapost  
  	%these colours affect fills, not the linework
  		!color colour_water_bg; %! forces interpretation as metapost
  		colour_water_bg := (0.86,1,1);      %light blue
  		!color colour_sump_bg;  %! forces interpretation as metapost
  		colour_sump_bg := (.22,.22,.95);    %dark blue
  	
      %these colours affect the linework	
  		!color colour_rope;  %! forces interpretation as metapost
  		colour_rope :=  (0.35,0.75,1.0);    %blue	
  		
  	%this colour for entrance symbol (not point station flag entrance)
  		!color colour_entrance;  %! forces interpretation as metapost
  		colour_entrance :=  (0.54,0.74,0.29);  		
      endcode
  endlayout LayoutColourSymbols

And the 'switch' that allows you to easily toggle from black and white to colour…
Just include this line in your thconfig file (or a layout referenced from the thconfig.

   copy LayoutColourSymbols #excludes labels
   

Comment it out when you want black and white.



Some more metapost examples (Bruce Mutton)

These include some similar to the above, a redefinition of Atlas so that it includes a north arrow on each page, and a redefinition of the continuation symbol so that it displays the associated text.



in case you use similar command:

   symbol-colour area blocks [67 31 4]
   code metapost
   def a_blocks (expr p) =
     T:=identity;
     pickup PenC;
     path q, qq; q = bbox p;
     picture tmp_pic; 
     uu := max(u, (xpart urcorner q - xpart llcorner q)/100, (ypart urcorner q - ypart llcorner q)/100);
     tmp_pic := image(
       for i = xpart llcorner q step 2uu until xpart urcorner q:
         for j = ypart llcorner q step 2uu until ypart urcorner q:
           qq := punked (((-.5uu,-.5uu)--(.5uu,-.5uu)--(.5uu,.5uu)--(-.5uu,.5uu)--cycle) 
          randomized (uu/2))
                rotated uniformdeviate(360) 
                shifted ((i,j) randomized 1.6uu);
           if xpart (p intersectiontimes qq) < 0:
                thdraw qq;
           fi;
         endfor;  
       endfor;
     );
     clip tmp_pic to p;
     draw tmp_pic;
   enddef;

This is modified a_blocks_SKBB definition with “thclean qq;” statement removed. Stacho Mudrák

Another solution

Another solution is to leave “thclean qq” on its original position and change

    clip tmp_pic to p;
    draw tmp_pic;

to

    clip tmp_pic to p;
    drawoptions();
    draw tmp_pic;

at the end of the macro definition. This approach preserves filling the blocks with a background colour. Martin Budaj



Q: Is there an additionally possibility to make this definition so that the area will be a bit transparent?

A: Try this code:

    def_transparent_rgb(tr_lgrey, 0.73, 0.71, 0.75);
    def a_u_lgrey(expr P) =
      T:=identity;
      thfill P withtransparentcolor tr_lgrey;
    enddef;

There are a few predefined transparent colors, the most interesting of them is tr_bg (current scrap background). Standard opacity value (defined in the layout section) is applied. M. Budaj



Line symbol for strata for cross sections. It works exactly as line section symbol but you should use -clip off option:

    def l_u_strata (expr P) =
      T:=identity;
      path Q; Q = punked P;
      for t = 0 upto length P - 1:
        pair zz[];
        zz1 := point t of P;
        zz2 := point t+1 of P;
        zz3 := postcontrol t of P;
        zz4 := precontrol t+1 of P;
        linecap:=0;
        if (length(zz3-1/3[zz1,zz2]) > 0.1pt) or
           (length(zz4-2/3[zz1,zz2]) > 0.1pt):
          zz5 = whatever[zz1,zz2];
          (zz3-zz5) = whatever * (zz1-zz2) rotated 90;
          pickup pencircle scaled 1 mm;
          draw zz1--zz5 dashed evenly;
          pickup PenA;
          draw zz1--zz5 withcolor background;
          zz6 = whatever[zz1,zz2];
          (zz4-zz6) = whatever * (zz1-zz2) rotated 90;
          pickup pencircle scaled 1 mm;
          draw zz2--zz6 dashed evenly;
          pickup PenA;
          draw zz2--zz6 withcolor background;
        else:
          pickup pencircle scaled 1 mm;
          draw zz1--zz2 dashed evenly;
          pickup PenA;
          draw zz1--zz2 withcolor background;
        fi;
      endfor;
    enddef;
    

Line symbol for fault. It works exactly as line section symbol but you should use -clip off option:

    def l_u_fault (expr P) =
      T:=identity;
      path Q; Q = punked P;
      pickup PenA;
      for t = 0 upto length P - 1:
        pair zz[];
        zz1 := point t of P;
        zz2 := point t+1 of P;
        zz3 := postcontrol t of P;
        zz4 := precontrol t+1 of P;
        if (length(zz3-1/3[zz1,zz2]) > 0.1pt) or
           (length(zz4-2/3[zz1,zz2]) > 0.1pt):
          zz5 = whatever[zz1,zz2];
          (zz3-zz5) = whatever * (zz1-zz2) rotated 90;
          draw zz1--zz5 dashed evenly;
          zz6 = whatever[zz1,zz2];
          (zz4-zz6) = whatever * (zz1-zz2) rotated 90;
          draw zz2--zz6 dashed evenly;
        else:
          draw zz1--zz2 dashed evenly;
        fi;
      endfor;
    enddef;